python2ts 1.1.0 → 1.2.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.
|
@@ -253,6 +253,23 @@ function declareVariable(ctx, name) {
|
|
|
253
253
|
currentScope.add(name);
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
|
+
function stripOuterParens(code) {
|
|
257
|
+
const trimmed = code.trim();
|
|
258
|
+
if (trimmed.startsWith("(") && trimmed.endsWith(")")) {
|
|
259
|
+
const inner = trimmed.slice(1, -1);
|
|
260
|
+
if (/(?<![!=<>])=(?!=)/.test(inner)) {
|
|
261
|
+
return code;
|
|
262
|
+
}
|
|
263
|
+
let depth = 0;
|
|
264
|
+
for (let i = 0; i < trimmed.length; i++) {
|
|
265
|
+
if (trimmed[i] === "(") depth++;
|
|
266
|
+
else if (trimmed[i] === ")") depth--;
|
|
267
|
+
if (depth === 0 && i < trimmed.length - 1) return code;
|
|
268
|
+
}
|
|
269
|
+
return inner;
|
|
270
|
+
}
|
|
271
|
+
return code;
|
|
272
|
+
}
|
|
256
273
|
function containsYield(node) {
|
|
257
274
|
if (node.name === "YieldStatement" || node.name === "YieldExpression") {
|
|
258
275
|
return true;
|
|
@@ -1076,7 +1093,7 @@ function transformConditionalExpression(node, ctx) {
|
|
|
1076
1093
|
const condition = exprs[1];
|
|
1077
1094
|
const falseExpr = exprs[2];
|
|
1078
1095
|
if (trueExpr && condition && falseExpr) {
|
|
1079
|
-
const condCode = transformNode(condition, ctx);
|
|
1096
|
+
const condCode = stripOuterParens(transformNode(condition, ctx));
|
|
1080
1097
|
const trueCode = transformNode(trueExpr, ctx);
|
|
1081
1098
|
const falseCode = transformNode(falseExpr, ctx);
|
|
1082
1099
|
return `(${condCode} ? ${trueCode} : ${falseCode})`;
|
|
@@ -1931,7 +1948,7 @@ function transformIfStatement(node, ctx) {
|
|
|
1931
1948
|
const condition = children[i + 1];
|
|
1932
1949
|
const body = children.find((c, idx) => idx > i && c.name === "Body");
|
|
1933
1950
|
if (condition && body) {
|
|
1934
|
-
const condCode = transformNode(condition, ctx);
|
|
1951
|
+
const condCode = stripOuterParens(transformNode(condition, ctx));
|
|
1935
1952
|
const bodyCode = transformBody(body, ctx);
|
|
1936
1953
|
parts.push(`if (${condCode}) {
|
|
1937
1954
|
${bodyCode}
|
|
@@ -1941,7 +1958,7 @@ ${bodyCode}
|
|
|
1941
1958
|
const condition = children[i + 1];
|
|
1942
1959
|
const body = children.find((c, idx) => idx > i + 1 && c.name === "Body");
|
|
1943
1960
|
if (condition && body) {
|
|
1944
|
-
const condCode = transformNode(condition, ctx);
|
|
1961
|
+
const condCode = stripOuterParens(transformNode(condition, ctx));
|
|
1945
1962
|
const bodyCode = transformBody(body, ctx);
|
|
1946
1963
|
parts.push(` else if (${condCode}) {
|
|
1947
1964
|
${bodyCode}
|
|
@@ -1967,7 +1984,7 @@ function transformWhileStatement(node, ctx) {
|
|
|
1967
1984
|
);
|
|
1968
1985
|
const body = children.find((c) => c.name === "Body");
|
|
1969
1986
|
if (!condition || !body) return getNodeText(node, ctx.source);
|
|
1970
|
-
const condCode = transformNode(condition, ctx);
|
|
1987
|
+
const condCode = stripOuterParens(transformNode(condition, ctx));
|
|
1971
1988
|
const bodyCode = transformBody(body, ctx);
|
|
1972
1989
|
return `while (${condCode}) {
|
|
1973
1990
|
${bodyCode}
|
|
@@ -2437,13 +2454,20 @@ ${baseIndent}}`;
|
|
|
2437
2454
|
const firstExcept = exceptBodies[0];
|
|
2438
2455
|
if (firstExcept) {
|
|
2439
2456
|
const catchVar = firstExcept.varName || "e";
|
|
2440
|
-
|
|
2457
|
+
let catchBody = transformBody(firstExcept.body, ctx);
|
|
2458
|
+
const isEmpty = !catchBody.trim();
|
|
2459
|
+
if (isEmpty) {
|
|
2460
|
+
const innerIndent = " ".repeat(ctx.indentLevel + 1);
|
|
2461
|
+
const exceptionComment = firstExcept.type ? ` - ${firstExcept.type} expected` : "";
|
|
2462
|
+
catchBody = `${innerIndent}// Intentionally empty${exceptionComment}`;
|
|
2463
|
+
}
|
|
2464
|
+
const catchClause = isEmpty && !firstExcept.varName ? "catch" : `catch (${catchVar})`;
|
|
2441
2465
|
if (exceptBodies.length === 1 && !firstExcept.type) {
|
|
2442
|
-
result += `
|
|
2466
|
+
result += ` ${catchClause} {
|
|
2443
2467
|
${catchBody}
|
|
2444
2468
|
${baseIndent}}`;
|
|
2445
2469
|
} else if (exceptBodies.length === 1) {
|
|
2446
|
-
result += `
|
|
2470
|
+
result += ` ${catchClause} {
|
|
2447
2471
|
${catchBody}
|
|
2448
2472
|
${baseIndent}}`;
|
|
2449
2473
|
} else {
|
|
@@ -4511,6 +4535,11 @@ function transformYieldStatement(node, ctx) {
|
|
|
4511
4535
|
|
|
4512
4536
|
// src/generator/index.ts
|
|
4513
4537
|
import * as prettier from "prettier";
|
|
4538
|
+
import { ESLint } from "eslint";
|
|
4539
|
+
import tseslint from "typescript-eslint";
|
|
4540
|
+
import { writeFileSync, readFileSync, mkdtempSync, rmSync } from "fs";
|
|
4541
|
+
import { join } from "path";
|
|
4542
|
+
import { tmpdir } from "os";
|
|
4514
4543
|
var defaultOptions = {
|
|
4515
4544
|
includeRuntime: true,
|
|
4516
4545
|
runtimeImportPath: "pythonlib"
|
|
@@ -4655,9 +4684,81 @@ function buildRuntimeImports(usedFunctions, basePath) {
|
|
|
4655
4684
|
function transpile(python, options = {}) {
|
|
4656
4685
|
return generate(python, options).code;
|
|
4657
4686
|
}
|
|
4687
|
+
function createEslintConfig(tempDir) {
|
|
4688
|
+
return {
|
|
4689
|
+
cwd: tempDir,
|
|
4690
|
+
fix: true,
|
|
4691
|
+
overrideConfigFile: true,
|
|
4692
|
+
overrideConfig: [
|
|
4693
|
+
// TypeScript-ESLint strict + stylistic presets (type-checked)
|
|
4694
|
+
...tseslint.configs.strictTypeChecked,
|
|
4695
|
+
...tseslint.configs.stylisticTypeChecked,
|
|
4696
|
+
// Custom configuration
|
|
4697
|
+
{
|
|
4698
|
+
files: ["**/*.ts"],
|
|
4699
|
+
languageOptions: {
|
|
4700
|
+
parserOptions: {
|
|
4701
|
+
projectService: true,
|
|
4702
|
+
tsconfigRootDir: tempDir
|
|
4703
|
+
}
|
|
4704
|
+
},
|
|
4705
|
+
rules: {
|
|
4706
|
+
// ESLint core rules (auto-fixable, not in typescript-eslint presets)
|
|
4707
|
+
"prefer-const": "error",
|
|
4708
|
+
"prefer-arrow-callback": "error",
|
|
4709
|
+
"prefer-template": "error",
|
|
4710
|
+
"prefer-rest-params": "error",
|
|
4711
|
+
"prefer-spread": "error",
|
|
4712
|
+
curly: "error",
|
|
4713
|
+
"no-lonely-if": "error",
|
|
4714
|
+
// Disable rules that don't make sense for generated code
|
|
4715
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
4716
|
+
"@typescript-eslint/explicit-module-boundary-types": "off",
|
|
4717
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
4718
|
+
"@typescript-eslint/no-unsafe-assignment": "off",
|
|
4719
|
+
"@typescript-eslint/no-unsafe-member-access": "off",
|
|
4720
|
+
"@typescript-eslint/no-unsafe-call": "off",
|
|
4721
|
+
"@typescript-eslint/no-unsafe-return": "off",
|
|
4722
|
+
"@typescript-eslint/no-unsafe-argument": "off"
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
]
|
|
4726
|
+
};
|
|
4727
|
+
}
|
|
4728
|
+
async function applyTypedEslintFixes(code) {
|
|
4729
|
+
const tempDir = mkdtempSync(join(tmpdir(), "python2ts-"));
|
|
4730
|
+
try {
|
|
4731
|
+
const tsconfigPath = join(tempDir, "tsconfig.json");
|
|
4732
|
+
writeFileSync(
|
|
4733
|
+
tsconfigPath,
|
|
4734
|
+
JSON.stringify({
|
|
4735
|
+
compilerOptions: {
|
|
4736
|
+
target: "ES2024",
|
|
4737
|
+
module: "ESNext",
|
|
4738
|
+
moduleResolution: "bundler",
|
|
4739
|
+
strict: true,
|
|
4740
|
+
skipLibCheck: true,
|
|
4741
|
+
noEmit: true
|
|
4742
|
+
},
|
|
4743
|
+
include: ["*.ts"]
|
|
4744
|
+
})
|
|
4745
|
+
);
|
|
4746
|
+
const tempFile = join(tempDir, "output.ts");
|
|
4747
|
+
writeFileSync(tempFile, code);
|
|
4748
|
+
const eslint = new ESLint(createEslintConfig(tempDir));
|
|
4749
|
+
const results = await eslint.lintFiles(["output.ts"]);
|
|
4750
|
+
if (results.length > 0 && results[0]?.output) {
|
|
4751
|
+
return results[0].output;
|
|
4752
|
+
}
|
|
4753
|
+
return readFileSync(tempFile, "utf-8");
|
|
4754
|
+
} finally {
|
|
4755
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
4756
|
+
}
|
|
4757
|
+
}
|
|
4658
4758
|
async function formatCode(code) {
|
|
4659
4759
|
try {
|
|
4660
|
-
|
|
4760
|
+
const eslintFixed = await applyTypedEslintFixes(code);
|
|
4761
|
+
return await prettier.format(eslintFixed, prettierOptions);
|
|
4661
4762
|
} catch {
|
|
4662
4763
|
return code;
|
|
4663
4764
|
}
|
|
@@ -4703,4 +4804,4 @@ export {
|
|
|
4703
4804
|
/* v8 ignore next -- bare yield statement @preserve */
|
|
4704
4805
|
/* v8 ignore next 2 -- fallback for future/unknown runtime functions @preserve */
|
|
4705
4806
|
/* v8 ignore start -- async wrappers tested via CLI @preserve */
|
|
4706
|
-
//# sourceMappingURL=chunk-
|
|
4807
|
+
//# sourceMappingURL=chunk-MEHQCUVO.js.map
|