python2ts 1.3.2 → 1.3.3

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.
@@ -262,6 +262,71 @@ function toJsName(pythonName) {
262
262
  }
263
263
 
264
264
  // src/transformer/index.ts
265
+ var JS_RESERVED_KEYWORDS = /* @__PURE__ */ new Set([
266
+ // ECMAScript reserved words
267
+ "break",
268
+ "case",
269
+ "catch",
270
+ "continue",
271
+ "debugger",
272
+ "default",
273
+ "delete",
274
+ "do",
275
+ "else",
276
+ "finally",
277
+ "for",
278
+ "function",
279
+ "if",
280
+ "in",
281
+ "instanceof",
282
+ "new",
283
+ "return",
284
+ "switch",
285
+ "this",
286
+ "throw",
287
+ "try",
288
+ "typeof",
289
+ "var",
290
+ "void",
291
+ "while",
292
+ "with",
293
+ // ECMAScript 6+ reserved words
294
+ "class",
295
+ "const",
296
+ "enum",
297
+ "export",
298
+ "extends",
299
+ "import",
300
+ // Note: 'super' is intentionally NOT in this list as it's valid in JS class contexts
301
+ // Strict mode reserved words
302
+ "implements",
303
+ "interface",
304
+ "let",
305
+ "package",
306
+ "private",
307
+ "protected",
308
+ "public",
309
+ "static",
310
+ "yield",
311
+ // TypeScript reserved words
312
+ "abstract",
313
+ "as",
314
+ "async",
315
+ "await",
316
+ "declare",
317
+ "from",
318
+ "get",
319
+ "is",
320
+ "module",
321
+ "namespace",
322
+ "of",
323
+ "require",
324
+ "set",
325
+ "type"
326
+ ]);
327
+ function escapeReservedKeyword(name) {
328
+ return JS_RESERVED_KEYWORDS.has(name) ? `_${name}` : name;
329
+ }
265
330
  function createContext(source) {
266
331
  return {
267
332
  source,
@@ -521,13 +586,23 @@ function isDocstringNode(node, ctx) {
521
586
  const firstChild = children[0];
522
587
  if (firstChild?.name !== "String") return false;
523
588
  const text = getNodeText(firstChild, ctx.source);
524
- return text.startsWith('"""') || text.startsWith("'''");
589
+ return isTripleQuotedString(text);
590
+ }
591
+ function isTripleQuotedString(text) {
592
+ let stripped = text;
593
+ if (/^[rRuU]/.test(text)) {
594
+ stripped = text.slice(1);
595
+ }
596
+ return stripped.startsWith('"""') || stripped.startsWith("'''");
525
597
  }
526
598
  function extractDocstringContent(node, ctx) {
527
599
  const children = getChildren(node);
528
600
  const stringNode = children[0];
529
601
  if (!stringNode) return "";
530
- const text = getNodeText(stringNode, ctx.source);
602
+ let text = getNodeText(stringNode, ctx.source);
603
+ if (/^[rRuU]/.test(text)) {
604
+ text = text.slice(1);
605
+ }
531
606
  let content = text;
532
607
  if (content.startsWith('"""')) {
533
608
  content = content.slice(3, -3);
@@ -737,7 +812,7 @@ function transformNode(node, ctx) {
737
812
  case "None":
738
813
  return "null";
739
814
  case "VariableName":
740
- return getNodeText(node, ctx.source);
815
+ return escapeReservedKeyword(getNodeText(node, ctx.source));
741
816
  case "CallExpression":
742
817
  return transformCallExpression(node, ctx);
743
818
  case "MemberExpression":
@@ -802,6 +877,9 @@ function transformNode(node, ctx) {
802
877
  return transformAssertStatement(node, ctx);
803
878
  case "YieldStatement":
804
879
  return transformYieldStatement(node, ctx);
880
+ case "Ellipsis":
881
+ ctx.usesRuntime.add("Ellipsis");
882
+ return "Ellipsis";
805
883
  /* v8 ignore next 2 -- fallback for unknown AST nodes @preserve */
806
884
  default:
807
885
  return getNodeText(node, ctx.source);
@@ -1839,7 +1917,11 @@ function transformMethodCall(callee, args, ctx) {
1839
1917
  case "rjust":
1840
1918
  return `${objCode}.padStart(${args})`;
1841
1919
  // String split/join - join is special: "sep".join(arr) -> arr.join("sep")
1920
+ // If the argument is a generator expression, convert to array with spread
1842
1921
  case "join":
1922
+ if (args.includes("function*")) {
1923
+ return `[...${args}].join(${objCode})`;
1924
+ }
1843
1925
  return `(${args}).join(${objCode})`;
1844
1926
  case "split":
1845
1927
  return args ? `${objCode}.split(${args})` : `${objCode}.split(/\\s+/)`;
@@ -2040,15 +2122,23 @@ function transformMemberExpression(node, ctx) {
2040
2122
  if (text.includes(":")) {
2041
2123
  return transformSliceFromMember(obj, children, ctx);
2042
2124
  }
2043
- const indexElements = children.filter((c) => c.name !== "[" && c.name !== "]" && c !== obj);
2044
- const index = indexElements[0];
2045
- if (!index) return `${objCode}[]`;
2046
- const indexCode = transformNode(index, ctx);
2047
- if (isNegativeIndexLiteral(index, ctx)) {
2048
- ctx.usesRuntime.add("at");
2049
- return `at(${objCode}, ${indexCode})`;
2125
+ const indexElements = children.filter(
2126
+ (c) => c.name !== "[" && c.name !== "]" && c.name !== "," && c !== obj
2127
+ );
2128
+ if (indexElements.length === 0) return `${objCode}[]`;
2129
+ if (indexElements.length === 1) {
2130
+ const index = indexElements[0];
2131
+ if (!index) return `${objCode}[]`;
2132
+ const indexCode = transformNode(index, ctx);
2133
+ if (isNegativeIndexLiteral(index, ctx)) {
2134
+ ctx.usesRuntime.add("at");
2135
+ return `at(${objCode}, ${indexCode})`;
2136
+ }
2137
+ return `${objCode}[${indexCode}]`;
2050
2138
  }
2051
- return `${objCode}[${indexCode}]`;
2139
+ ctx.usesRuntime.add("tuple");
2140
+ const indices = indexElements.map((el) => transformNode(el, ctx));
2141
+ return `${objCode}[tuple(${indices.join(", ")})]`;
2052
2142
  } else {
2053
2143
  const prop = children[children.length - 1];
2054
2144
  if (!prop) return getNodeText(node, ctx.source);
@@ -3130,7 +3220,7 @@ function extractParamNames(node, source) {
3130
3220
  if (child.name === "*" || getNodeText(child, source) === "*") {
3131
3221
  const nextChild = children[i + 1];
3132
3222
  if (nextChild?.name === "VariableName") {
3133
- names.push(getNodeText(nextChild, source));
3223
+ names.push(escapeReservedKeyword(getNodeText(nextChild, source)));
3134
3224
  i += 2;
3135
3225
  continue;
3136
3226
  }
@@ -3140,7 +3230,7 @@ function extractParamNames(node, source) {
3140
3230
  if (child.name === "**" || getNodeText(child, source) === "**") {
3141
3231
  const nextChild = children[i + 1];
3142
3232
  if (nextChild?.name === "VariableName") {
3143
- names.push(getNodeText(nextChild, source));
3233
+ names.push(escapeReservedKeyword(getNodeText(nextChild, source)));
3144
3234
  i += 2;
3145
3235
  continue;
3146
3236
  }
@@ -3148,7 +3238,7 @@ function extractParamNames(node, source) {
3148
3238
  continue;
3149
3239
  }
3150
3240
  if (child.name === "VariableName") {
3151
- names.push(getNodeText(child, source));
3241
+ names.push(escapeReservedKeyword(getNodeText(child, source)));
3152
3242
  i++;
3153
3243
  continue;
3154
3244
  }
@@ -3156,7 +3246,7 @@ function extractParamNames(node, source) {
3156
3246
  const paramChildren = getChildren(child);
3157
3247
  const name = paramChildren.find((c) => c.name === "VariableName");
3158
3248
  if (name) {
3159
- names.push(getNodeText(name, source));
3249
+ names.push(escapeReservedKeyword(getNodeText(name, source)));
3160
3250
  }
3161
3251
  i++;
3162
3252
  continue;
@@ -4278,7 +4368,7 @@ function transformParamList(node, ctx) {
4278
4368
  const parseParam = (startIndex) => {
4279
4369
  const child = children[startIndex];
4280
4370
  if (child?.name !== "VariableName") return null;
4281
- const nameCode = getNodeText(child, ctx.source);
4371
+ const nameCode = escapeReservedKeyword(getNodeText(child, ctx.source));
4282
4372
  let tsType = null;
4283
4373
  let defaultValue = null;
4284
4374
  let offset = 1;
@@ -4320,7 +4410,7 @@ function transformParamList(node, ctx) {
4320
4410
  if (child.name === "*" || getNodeText(child, ctx.source) === "*") {
4321
4411
  const nextChild = children[i + 1];
4322
4412
  if (nextChild?.name === "VariableName") {
4323
- const name = getNodeText(nextChild, ctx.source);
4413
+ const name = escapeReservedKeyword(getNodeText(nextChild, ctx.source));
4324
4414
  const typeChild = children[i + 2];
4325
4415
  if (typeChild?.name === "TypeDef") {
4326
4416
  const tsType = extractTypeAnnotation(typeChild, ctx);
@@ -4340,7 +4430,7 @@ function transformParamList(node, ctx) {
4340
4430
  if (child.name === "**" || getNodeText(child, ctx.source) === "**") {
4341
4431
  const nextChild = children[i + 1];
4342
4432
  if (nextChild?.name === "VariableName") {
4343
- kwargsParam = getNodeText(nextChild, ctx.source);
4433
+ kwargsParam = escapeReservedKeyword(getNodeText(nextChild, ctx.source));
4344
4434
  i += 2;
4345
4435
  continue;
4346
4436
  }
@@ -4365,7 +4455,7 @@ function transformParamList(node, ctx) {
4365
4455
  const typeDef = paramChildren.find((c) => c.name === "TypeDef");
4366
4456
  const defaultVal = paramChildren[paramChildren.length - 1];
4367
4457
  if (name) {
4368
- const nameCode = getNodeText(name, ctx.source);
4458
+ const nameCode = escapeReservedKeyword(getNodeText(name, ctx.source));
4369
4459
  const tsType = extractTypeAnnotation(typeDef, ctx);
4370
4460
  let defaultValue = null;
4371
4461
  if (defaultVal && name !== defaultVal && defaultVal.name !== "TypeDef") {
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-RNRRQS6K.js";
4
+ } from "../chunk-TBFKEIAB.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-RNRRQS6K.js";
15
+ } from "./chunk-TBFKEIAB.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.2",
3
+ "version": "1.3.3",
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": {
@@ -53,7 +53,7 @@
53
53
  "eslint": "^9.39.2",
54
54
  "prettier": "^3.8.0",
55
55
  "typescript-eslint": "^8.53.1",
56
- "pythonlib": "2.0.2"
56
+ "pythonlib": "2.0.3"
57
57
  },
58
58
  "devDependencies": {
59
59
  "tsup": "^8.5.1",