python2ts 1.2.0 → 1.3.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.
@@ -214,7 +214,48 @@ var PYTHON_TO_JS_NAMES = {
214
214
  // core module
215
215
  // ============================================================================
216
216
  floordiv: "floorDiv",
217
- divmod: "divMod"
217
+ divmod: "divMod",
218
+ // ============================================================================
219
+ // hashlib module
220
+ // ============================================================================
221
+ pbkdf2_hmac: "pbkdf2Hmac",
222
+ compare_digest: "compareDigest",
223
+ file_digest: "fileDigest",
224
+ new: "newHash",
225
+ // ============================================================================
226
+ // pathlib module (Path methods)
227
+ // ============================================================================
228
+ read_text: "readText",
229
+ write_text: "writeText",
230
+ read_bytes: "readBytes",
231
+ write_bytes: "writeBytes",
232
+ is_file: "isFile",
233
+ is_dir: "isDir",
234
+ is_symlink: "isSymlink",
235
+ symlink_to: "symlinkTo",
236
+ link_to: "linkTo",
237
+ // ============================================================================
238
+ // shutil module
239
+ // ============================================================================
240
+ copy2: "copy2",
241
+ copytree: "copytree",
242
+ rmtree: "rmtree",
243
+ disk_usage: "diskUsage",
244
+ copymode: "copyMode",
245
+ copystat: "copyStat",
246
+ copyfile: "copyFile",
247
+ get_terminal_size: "getTerminalSize",
248
+ // ============================================================================
249
+ // tempfile module
250
+ // ============================================================================
251
+ mkstemp: "mkstemp",
252
+ mkdtemp: "mkdtemp",
253
+ gettempdir: "getTempDir",
254
+ // ============================================================================
255
+ // glob module
256
+ // ============================================================================
257
+ iglob: "iglob",
258
+ rglob: "rglob"
218
259
  };
219
260
  function toJsName(pythonName) {
220
261
  return PYTHON_TO_JS_NAMES[pythonName] ?? pythonName;
@@ -412,7 +453,7 @@ function transformPythonType(node, ctx) {
412
453
  }
413
454
  }
414
455
  function extractTypeAnnotation(typeDef, ctx) {
415
- if (!typeDef || typeDef.name !== "TypeDef") return null;
456
+ if (typeDef?.name !== "TypeDef") return null;
416
457
  const children = getChildren(typeDef);
417
458
  const typeNode = children.find((c) => c.name !== ":" && c.name !== "->");
418
459
  if (typeNode) {
@@ -422,7 +463,7 @@ function extractTypeAnnotation(typeDef, ctx) {
422
463
  }
423
464
  function extractTypeModifiers(typeDef, ctx) {
424
465
  const result = { isFinal: false, isClassVar: false };
425
- if (!typeDef || typeDef.name !== "TypeDef") return result;
466
+ if (typeDef?.name !== "TypeDef") return result;
426
467
  const children = getChildren(typeDef);
427
468
  const typeNode = children.find((c) => c.name !== ":" && c.name !== "->");
428
469
  if (!typeNode) return result;
@@ -478,7 +519,7 @@ function isDocstringNode(node, ctx) {
478
519
  if (node.name !== "ExpressionStatement") return false;
479
520
  const children = getChildren(node);
480
521
  const firstChild = children[0];
481
- if (!firstChild || firstChild.name !== "String") return false;
522
+ if (firstChild?.name !== "String") return false;
482
523
  const text = getNodeText(firstChild, ctx.source);
483
524
  return text.startsWith('"""') || text.startsWith("'''");
484
525
  }
@@ -561,7 +602,7 @@ function parseDocstring(content) {
561
602
  descriptionLines.push(trimmed);
562
603
  break;
563
604
  case "params": {
564
- const googleMatch = trimmed.match(/^(\w+)\s*(?:\([^)]*\))?\s*:\s*(.*)$/);
605
+ const googleMatch = /^(\w+)\s*(?:\([^)]*\))?\s*:\s*(.*)$/.exec(trimmed);
565
606
  if (googleMatch) {
566
607
  flushParam();
567
608
  currentParamName = googleMatch[1] ?? "";
@@ -589,7 +630,7 @@ function parseDocstring(content) {
589
630
  break;
590
631
  }
591
632
  case "throws": {
592
- const throwsMatch = trimmed.match(/^(\w+)\s*:\s*(.*)$/);
633
+ const throwsMatch = /^(\w+)\s*:\s*(.*)$/.exec(trimmed);
593
634
  if (throwsMatch) {
594
635
  flushThrows();
595
636
  currentThrowsType = throwsMatch[1] ?? "Error";
@@ -1043,7 +1084,7 @@ function isChainedComparison(node) {
1043
1084
  if (node.name !== "BinaryExpression") return false;
1044
1085
  const children = getChildren(node);
1045
1086
  const op = children[1];
1046
- if (!op || op.name !== "CompareOp") return false;
1087
+ if (op?.name !== "CompareOp") return false;
1047
1088
  return true;
1048
1089
  }
1049
1090
  function extractRightOperand(node, ctx) {
@@ -1435,6 +1476,52 @@ function transformCallExpression(node, ctx) {
1435
1476
  case "capwords":
1436
1477
  ctx.usesRuntime.add("string/capWords");
1437
1478
  return `capWords(${args})`;
1479
+ // glob module - async functions (direct import)
1480
+ case "glob":
1481
+ ctx.usesRuntime.add("glob/glob");
1482
+ return `await glob(${args})`;
1483
+ case "iglob":
1484
+ ctx.usesRuntime.add("glob/iglob");
1485
+ return `await iglob(${args})`;
1486
+ case "rglob":
1487
+ ctx.usesRuntime.add("glob/rglob");
1488
+ return `await rglob(${args})`;
1489
+ // shutil module - async functions (direct import)
1490
+ case "copy":
1491
+ ctx.usesRuntime.add("shutil/copy");
1492
+ return `await copy(${args})`;
1493
+ case "copy2":
1494
+ ctx.usesRuntime.add("shutil/copy2");
1495
+ return `await copy2(${args})`;
1496
+ case "copytree":
1497
+ ctx.usesRuntime.add("shutil/copytree");
1498
+ return `await copytree(${args})`;
1499
+ case "move":
1500
+ ctx.usesRuntime.add("shutil/move");
1501
+ return `await move(${args})`;
1502
+ case "rmtree":
1503
+ ctx.usesRuntime.add("shutil/rmtree");
1504
+ return `await rmtree(${args})`;
1505
+ case "which":
1506
+ ctx.usesRuntime.add("shutil/which");
1507
+ return `await which(${args})`;
1508
+ // tempfile module - async functions (direct import)
1509
+ case "mkstemp":
1510
+ ctx.usesRuntime.add("tempfile/mkstemp");
1511
+ return `await mkstemp(${args})`;
1512
+ case "mkdtemp":
1513
+ ctx.usesRuntime.add("tempfile/mkdtemp");
1514
+ return `await mkdtemp(${args})`;
1515
+ case "NamedTemporaryFile":
1516
+ ctx.usesRuntime.add("tempfile/NamedTemporaryFile");
1517
+ return `await NamedTemporaryFile.create(${args})`;
1518
+ case "TemporaryDirectory":
1519
+ ctx.usesRuntime.add("tempfile/TemporaryDirectory");
1520
+ return `await TemporaryDirectory.create(${args})`;
1521
+ // pathlib module
1522
+ case "Path":
1523
+ ctx.usesRuntime.add("pathlib/Path");
1524
+ return `new Path(${args})`;
1438
1525
  /* v8 ignore next 3 -- pass-through for user-defined functions @preserve */
1439
1526
  default:
1440
1527
  return `${transformNode(callee, ctx)}(${args})`;
@@ -1453,9 +1540,10 @@ function transformModuleCall(calleeName, args, ctx) {
1453
1540
  inf: "inf",
1454
1541
  nan: "nan"
1455
1542
  };
1456
- if (funcName in mathConstants) {
1543
+ const mathConstant = mathConstants[funcName];
1544
+ if (mathConstant !== void 0) {
1457
1545
  ctx.usesRuntime.add(`math/${funcName}`);
1458
- return mathConstants[funcName];
1546
+ return mathConstant;
1459
1547
  }
1460
1548
  ctx.usesRuntime.add(`math/${funcName}`);
1461
1549
  return `${funcName}(${args})`;
@@ -1470,14 +1558,45 @@ function transformModuleCall(calleeName, args, ctx) {
1470
1558
  return `${funcName}(${args})`;
1471
1559
  }
1472
1560
  if (moduleName === "os") {
1561
+ const asyncPathFuncs = [
1562
+ "exists",
1563
+ "isfile",
1564
+ "isdir",
1565
+ "islink",
1566
+ "realpath",
1567
+ "getsize",
1568
+ "getmtime",
1569
+ "getatime",
1570
+ "getctime"
1571
+ ];
1572
+ const asyncOsFuncs = [
1573
+ "listdir",
1574
+ "mkdir",
1575
+ "makedirs",
1576
+ "remove",
1577
+ "unlink",
1578
+ "rmdir",
1579
+ "removedirs",
1580
+ "rename",
1581
+ "renames",
1582
+ "replace",
1583
+ "walk",
1584
+ "stat"
1585
+ ];
1473
1586
  if (funcName.startsWith("path.")) {
1474
1587
  const pathFuncName = funcName.slice(5);
1475
1588
  const jsPathFunc = toJsName(pathFuncName);
1476
1589
  ctx.usesRuntime.add("os/path");
1590
+ if (asyncPathFuncs.includes(pathFuncName.toLowerCase())) {
1591
+ return `await path.${jsPathFunc}(${args})`;
1592
+ }
1477
1593
  return `path.${jsPathFunc}(${args})`;
1478
1594
  }
1479
1595
  const jsName = toJsName(funcName);
1480
1596
  ctx.usesRuntime.add(`os/${jsName}`);
1597
+ if (asyncOsFuncs.includes(funcName.toLowerCase())) {
1598
+ return `await ${jsName}(${args})`;
1599
+ }
1481
1600
  return `${jsName}(${args})`;
1482
1601
  }
1483
1602
  if (moduleName === "datetime") {
@@ -1518,6 +1637,67 @@ function transformModuleCall(calleeName, args, ctx) {
1518
1637
  }
1519
1638
  return `${funcName}(${args})`;
1520
1639
  }
1640
+ if (moduleName === "hashlib") {
1641
+ const jsName = toJsName(funcName);
1642
+ ctx.usesRuntime.add(`hashlib/${jsName}`);
1643
+ if (["pbkdf2_hmac", "scrypt", "compare_digest", "file_digest"].includes(funcName)) {
1644
+ const asyncJsName = toJsName(funcName);
1645
+ return `await ${asyncJsName}(${args})`;
1646
+ }
1647
+ return `${jsName}(${args})`;
1648
+ }
1649
+ if (moduleName === "shutil") {
1650
+ const asyncShutilFuncs = [
1651
+ "copy",
1652
+ "copy2",
1653
+ "copytree",
1654
+ "move",
1655
+ "rmtree",
1656
+ "which",
1657
+ "disk_usage",
1658
+ "copymode",
1659
+ "copystat",
1660
+ "copyfile"
1661
+ ];
1662
+ const jsName = toJsName(funcName);
1663
+ ctx.usesRuntime.add(`shutil/${jsName}`);
1664
+ if (asyncShutilFuncs.includes(funcName.toLowerCase())) {
1665
+ return `await ${jsName}(${args})`;
1666
+ }
1667
+ return `${jsName}(${args})`;
1668
+ }
1669
+ if (moduleName === "glob") {
1670
+ const asyncGlobFuncs = ["glob", "iglob", "rglob"];
1671
+ const jsName = toJsName(funcName);
1672
+ ctx.usesRuntime.add(`glob/${jsName}`);
1673
+ if (asyncGlobFuncs.includes(funcName.toLowerCase())) {
1674
+ return `await ${jsName}(${args})`;
1675
+ }
1676
+ return `${jsName}(${args})`;
1677
+ }
1678
+ if (moduleName === "tempfile") {
1679
+ const asyncTempfileFuncs = ["mkstemp", "mkdtemp"];
1680
+ const jsName = toJsName(funcName);
1681
+ ctx.usesRuntime.add(`tempfile/${jsName}`);
1682
+ if (funcName === "NamedTemporaryFile") {
1683
+ return `await NamedTemporaryFile.create(${args})`;
1684
+ }
1685
+ if (funcName === "TemporaryDirectory") {
1686
+ return `await TemporaryDirectory.create(${args})`;
1687
+ }
1688
+ if (asyncTempfileFuncs.includes(funcName.toLowerCase())) {
1689
+ return `await ${jsName}(${args})`;
1690
+ }
1691
+ return `${jsName}(${args})`;
1692
+ }
1693
+ if (moduleName === "pathlib") {
1694
+ const jsName = toJsName(funcName);
1695
+ ctx.usesRuntime.add(`pathlib/${jsName}`);
1696
+ if (funcName === "Path") {
1697
+ return `new Path(${args})`;
1698
+ }
1699
+ return `${jsName}(${args})`;
1700
+ }
1521
1701
  return null;
1522
1702
  }
1523
1703
  function transformMethodCall(callee, args, ctx) {
@@ -1529,6 +1709,29 @@ function transformMethodCall(callee, args, ctx) {
1529
1709
  if (obj.name === "MemberExpression") {
1530
1710
  return null;
1531
1711
  }
1712
+ if (obj.name === "VariableName") {
1713
+ const objName = getNodeText(obj, ctx.source);
1714
+ const knownModules = [
1715
+ "shutil",
1716
+ "glob",
1717
+ "tempfile",
1718
+ "pathlib",
1719
+ "os",
1720
+ "math",
1721
+ "random",
1722
+ "json",
1723
+ "datetime",
1724
+ "re",
1725
+ "string",
1726
+ "functools",
1727
+ "itertools",
1728
+ "collections",
1729
+ "hashlib"
1730
+ ];
1731
+ if (knownModules.includes(objName)) {
1732
+ return null;
1733
+ }
1734
+ }
1532
1735
  const objCode = transformNode(obj, ctx);
1533
1736
  const methodName = getNodeText(methodNode, ctx.source);
1534
1737
  switch (methodName) {
@@ -1687,6 +1890,26 @@ function transformMethodCall(callee, args, ctx) {
1687
1890
  case "issuperset":
1688
1891
  ctx.usesRuntime.add("set");
1689
1892
  return `set.issuperset(${objCode}, ${args})`;
1893
+ // Hash object methods (hashlib) - async
1894
+ case "digest":
1895
+ return `await ${objCode}.digest()`;
1896
+ case "hexdigest":
1897
+ return `await ${objCode}.hexdigest()`;
1898
+ // Path object methods (pathlib) - async
1899
+ // Only handle snake_case methods that are unique to Path
1900
+ case "is_file":
1901
+ case "is_dir":
1902
+ case "is_symlink":
1903
+ case "read_text":
1904
+ case "write_text":
1905
+ case "read_bytes":
1906
+ case "write_bytes":
1907
+ case "symlink_to":
1908
+ case "link_to":
1909
+ case "iterdir": {
1910
+ const jsMethod = toJsName(methodName);
1911
+ return `await ${objCode}.${jsMethod}(${args})`;
1912
+ }
1690
1913
  /* v8 ignore next 2 -- unknown method, let caller handle @preserve */
1691
1914
  default:
1692
1915
  return null;
@@ -1734,7 +1957,7 @@ function transformArgList(node, ctx) {
1734
1957
  }
1735
1958
  if (item.name === "VariableName") {
1736
1959
  const nextItem = items[i + 1];
1737
- if (nextItem && nextItem.name === "AssignOp") {
1960
+ if (nextItem?.name === "AssignOp") {
1738
1961
  const valueItem = items[i + 2];
1739
1962
  if (valueItem) {
1740
1963
  const name = getNodeText(item, ctx.source);
@@ -1998,8 +2221,8 @@ function transformMatchStatement(node, ctx) {
1998
2221
  if (child.name === "match" || child.name === ":") continue;
1999
2222
  if (child.name === "MatchBody") {
2000
2223
  matchBody = child;
2001
- } else if (!subject) {
2002
- subject = child;
2224
+ } else {
2225
+ subject ??= child;
2003
2226
  }
2004
2227
  }
2005
2228
  if (!subject || !matchBody) return getNodeText(node, ctx.source);
@@ -2049,8 +2272,8 @@ function transformMatchAsIfElse(subjectCode, clauses, ctx) {
2049
2272
  body = child;
2050
2273
  } else if (child.name === "Guard") {
2051
2274
  guard = child;
2052
- } else if (!pattern) {
2053
- pattern = child;
2275
+ } else {
2276
+ pattern ??= child;
2054
2277
  }
2055
2278
  }
2056
2279
  if (!pattern || !body) continue;
@@ -2276,8 +2499,8 @@ function transformMatchClause(node, ctx, indent) {
2276
2499
  if (child.name === "case" || child.name === ":") continue;
2277
2500
  if (child.name === "Body") {
2278
2501
  body = child;
2279
- } else if (!pattern) {
2280
- pattern = child;
2502
+ } else {
2503
+ pattern ??= child;
2281
2504
  }
2282
2505
  }
2283
2506
  if (!pattern || !body) return "";
@@ -2397,7 +2620,7 @@ function transformTryStatement(node, ctx) {
2397
2620
  }
2398
2621
  if (child.name === "try") {
2399
2622
  const nextBody = children[i + 1];
2400
- if (nextBody && nextBody.name === "Body") {
2623
+ if (nextBody?.name === "Body") {
2401
2624
  tryBody = nextBody;
2402
2625
  i += 2;
2403
2626
  continue;
@@ -2435,7 +2658,7 @@ function transformTryStatement(node, ctx) {
2435
2658
  }
2436
2659
  if (child.name === "finally") {
2437
2660
  const nextBody = children[i + 1];
2438
- if (nextBody && nextBody.name === "Body") {
2661
+ if (nextBody?.name === "Body") {
2439
2662
  finallyBody = nextBody;
2440
2663
  i += 2;
2441
2664
  continue;
@@ -2453,7 +2676,7 @@ ${baseIndent}}`;
2453
2676
  if (exceptBodies.length > 0) {
2454
2677
  const firstExcept = exceptBodies[0];
2455
2678
  if (firstExcept) {
2456
- const catchVar = firstExcept.varName || "e";
2679
+ const catchVar = firstExcept.varName ?? "e";
2457
2680
  let catchBody = transformBody(firstExcept.body, ctx);
2458
2681
  const isEmpty = !catchBody.trim();
2459
2682
  if (isEmpty) {
@@ -2477,7 +2700,7 @@ ${baseIndent}}`;
2477
2700
  const exc = exceptBodies[idx];
2478
2701
  if (!exc) continue;
2479
2702
  const excBodyCode = transformBody(exc.body, ctx);
2480
- const excVar = exc.varName || catchVar;
2703
+ const excVar = exc.varName ?? catchVar;
2481
2704
  if (exc.type) {
2482
2705
  const condition = idx === 0 ? "if" : "} else if";
2483
2706
  const mappedType = mapExceptionType(exc.type);
@@ -2532,7 +2755,7 @@ function mapExceptionType(pythonType) {
2532
2755
  NameError: "ReferenceError",
2533
2756
  SyntaxError: "SyntaxError"
2534
2757
  };
2535
- return mapping[pythonType] || "Error";
2758
+ return mapping[pythonType] ?? "Error";
2536
2759
  }
2537
2760
  function transformRaiseStatement(node, ctx) {
2538
2761
  const children = getChildren(node);
@@ -2622,9 +2845,9 @@ function transformSimpleImport(children, ctx) {
2622
2845
  const moduleName = getNodeText(child, ctx.source);
2623
2846
  let alias = null;
2624
2847
  const nextChild = children[i + 1];
2625
- if (nextChild && nextChild.name === "as") {
2848
+ if (nextChild?.name === "as") {
2626
2849
  const aliasChild = children[i + 2];
2627
- if (aliasChild && aliasChild.name === "VariableName") {
2850
+ if (aliasChild?.name === "VariableName") {
2628
2851
  alias = getNodeText(aliasChild, ctx.source);
2629
2852
  i += 3;
2630
2853
  names.push({ module: moduleName, alias });
@@ -2644,7 +2867,7 @@ function transformSimpleImport(children, ctx) {
2644
2867
  return "";
2645
2868
  }
2646
2869
  return filteredNames.map(({ module, alias }) => {
2647
- const importName = alias || module;
2870
+ const importName = alias ?? module;
2648
2871
  return `import * as ${importName} from "${module}"`;
2649
2872
  }).join("\n");
2650
2873
  }
@@ -2720,9 +2943,9 @@ function transformFromImport(children, ctx) {
2720
2943
  if (child.name === "VariableName") {
2721
2944
  const name = getNodeText(child, ctx.source);
2722
2945
  const nextChild = children[i + 1];
2723
- if (nextChild && nextChild.name === "as") {
2946
+ if (nextChild?.name === "as") {
2724
2947
  const aliasChild = children[i + 2];
2725
- if (aliasChild && aliasChild.name === "VariableName") {
2948
+ if (aliasChild?.name === "VariableName") {
2726
2949
  imports.push({ name, alias: getNodeText(aliasChild, ctx.source) });
2727
2950
  i += 2;
2728
2951
  continue;
@@ -2746,7 +2969,7 @@ function transformFromImport(children, ctx) {
2746
2969
  if (moduleName) {
2747
2970
  modulePath += moduleName;
2748
2971
  } else if (imports.length > 0) {
2749
- modulePath += imports[0]?.name || "";
2972
+ modulePath += imports[0]?.name ?? "";
2750
2973
  }
2751
2974
  } else {
2752
2975
  modulePath = moduleName;
@@ -2757,7 +2980,7 @@ function transformFromImport(children, ctx) {
2757
2980
  if (relativeDots > 0 && !moduleName && imports.length === 1) {
2758
2981
  const imp = imports[0];
2759
2982
  if (imp) {
2760
- const importName = imp.alias || imp.name;
2983
+ const importName = imp.alias ?? imp.name;
2761
2984
  return `import * as ${importName} from "${modulePath}"`;
2762
2985
  }
2763
2986
  }
@@ -2796,9 +3019,9 @@ function transformWithStatement(node, ctx) {
2796
3019
  const expr = child;
2797
3020
  let varName = null;
2798
3021
  const nextChild = children[i + 1];
2799
- if (nextChild && nextChild.name === "as") {
3022
+ if (nextChild?.name === "as") {
2800
3023
  const varChild = children[i + 2];
2801
- if (varChild && varChild.name === "VariableName") {
3024
+ if (varChild?.name === "VariableName") {
2802
3025
  varName = getNodeText(varChild, ctx.source);
2803
3026
  i += 3;
2804
3027
  } else {
@@ -2871,7 +3094,7 @@ function extractParamNames(node, source) {
2871
3094
  }
2872
3095
  if (child.name === "*" || getNodeText(child, source) === "*") {
2873
3096
  const nextChild = children[i + 1];
2874
- if (nextChild && nextChild.name === "VariableName") {
3097
+ if (nextChild?.name === "VariableName") {
2875
3098
  names.push(getNodeText(nextChild, source));
2876
3099
  i += 2;
2877
3100
  continue;
@@ -2881,7 +3104,7 @@ function extractParamNames(node, source) {
2881
3104
  }
2882
3105
  if (child.name === "**" || getNodeText(child, source) === "**") {
2883
3106
  const nextChild = children[i + 1];
2884
- if (nextChild && nextChild.name === "VariableName") {
3107
+ if (nextChild?.name === "VariableName") {
2885
3108
  names.push(getNodeText(nextChild, source));
2886
3109
  i += 2;
2887
3110
  continue;
@@ -3252,7 +3475,7 @@ function transformMethodParamListImpl(node, ctx, includeTypes) {
3252
3475
  isFirstParam = false;
3253
3476
  if (child.name === "*" || getNodeText(child, ctx.source) === "*") {
3254
3477
  const nextChild = children[i + 1];
3255
- if (nextChild && nextChild.name === "VariableName") {
3478
+ if (nextChild?.name === "VariableName") {
3256
3479
  const name = getNodeText(nextChild, ctx.source);
3257
3480
  params.push(`...${name}`);
3258
3481
  i += 2;
@@ -3263,7 +3486,7 @@ function transformMethodParamListImpl(node, ctx, includeTypes) {
3263
3486
  }
3264
3487
  if (child.name === "**" || getNodeText(child, ctx.source) === "**") {
3265
3488
  const nextChild = children[i + 1];
3266
- if (nextChild && nextChild.name === "VariableName") {
3489
+ if (nextChild?.name === "VariableName") {
3267
3490
  const name = getNodeText(nextChild, ctx.source);
3268
3491
  params.push(name);
3269
3492
  i += 2;
@@ -3606,7 +3829,7 @@ function parseDataclassFieldFromExpression(node, ctx) {
3606
3829
  }
3607
3830
  function parseFieldDefaultFactory(callNode, ctx) {
3608
3831
  const text = getNodeText(callNode, ctx.source);
3609
- const factoryMatch = text.match(/default_factory\s*=\s*(\w+)/);
3832
+ const factoryMatch = /default_factory\s*=\s*(\w+)/.exec(text);
3610
3833
  if (factoryMatch) {
3611
3834
  const factory = factoryMatch[1];
3612
3835
  if (factory === "list") return "[]";
@@ -3614,7 +3837,7 @@ function parseFieldDefaultFactory(callNode, ctx) {
3614
3837
  if (factory === "set") return "new Set()";
3615
3838
  if (factory) return `${factory}()`;
3616
3839
  }
3617
- const defaultMatch = text.match(/default\s*=\s*([^,)]+)/);
3840
+ const defaultMatch = /default\s*=\s*([^,)]+)/.exec(text);
3618
3841
  if (defaultMatch) {
3619
3842
  return defaultMatch[1]?.trim() ?? "undefined";
3620
3843
  }
@@ -3833,9 +4056,8 @@ function parseEnumMember(node, ctx) {
3833
4056
  function checkSequentialEnum(members) {
3834
4057
  if (members.length === 0) return true;
3835
4058
  if (members.some((m) => m.value === "auto")) return true;
3836
- const numericMembers = members.filter((m) => m.numericValue !== null);
3837
- if (numericMembers.length !== members.length) return false;
3838
- const values = numericMembers.map((m) => m.numericValue);
4059
+ const values = members.map((m) => m.numericValue).filter((v) => v !== null);
4060
+ if (values.length !== members.length) return false;
3839
4061
  const firstValue = values[0];
3840
4062
  if (firstValue === void 0) return false;
3841
4063
  for (let i = 1; i < values.length; i++) {
@@ -3917,7 +4139,7 @@ function transformProtocol(className, parentClasses, body, ctx) {
3917
4139
  members.push(`${memberIndent}${sig}`);
3918
4140
  }
3919
4141
  } else if (child.name === "ExpressionStatement" || child.name === "AssignStatement") {
3920
- const field = parseDataclassFieldFromExpression(child, ctx) || parseDataclassFieldFromAssignment(child, ctx);
4142
+ const field = parseDataclassFieldFromExpression(child, ctx) ?? parseDataclassFieldFromAssignment(child, ctx);
3921
4143
  if (field) {
3922
4144
  members.push(`${memberIndent}${field.name}: ${field.tsType}`);
3923
4145
  }
@@ -4016,18 +4238,18 @@ function transformParamList(node, ctx) {
4016
4238
  let i = 0;
4017
4239
  const parseParam = (startIndex) => {
4018
4240
  const child = children[startIndex];
4019
- if (!child || child.name !== "VariableName") return null;
4241
+ if (child?.name !== "VariableName") return null;
4020
4242
  const nameCode = getNodeText(child, ctx.source);
4021
4243
  let tsType = null;
4022
4244
  let defaultValue = null;
4023
4245
  let offset = 1;
4024
4246
  const nextChild = children[startIndex + 1];
4025
- if (nextChild && nextChild.name === "TypeDef") {
4247
+ if (nextChild?.name === "TypeDef") {
4026
4248
  tsType = extractTypeAnnotation(nextChild, ctx);
4027
4249
  offset = 2;
4028
4250
  }
4029
4251
  const afterType = children[startIndex + offset];
4030
- if (afterType && afterType.name === "AssignOp") {
4252
+ if (afterType?.name === "AssignOp") {
4031
4253
  const defaultValChild = children[startIndex + offset + 1];
4032
4254
  if (defaultValChild) {
4033
4255
  defaultValue = transformNode(defaultValChild, ctx);
@@ -4058,10 +4280,10 @@ function transformParamList(node, ctx) {
4058
4280
  }
4059
4281
  if (child.name === "*" || getNodeText(child, ctx.source) === "*") {
4060
4282
  const nextChild = children[i + 1];
4061
- if (nextChild && nextChild.name === "VariableName") {
4283
+ if (nextChild?.name === "VariableName") {
4062
4284
  const name = getNodeText(nextChild, ctx.source);
4063
4285
  const typeChild = children[i + 2];
4064
- if (typeChild && typeChild.name === "TypeDef") {
4286
+ if (typeChild?.name === "TypeDef") {
4065
4287
  const tsType = extractTypeAnnotation(typeChild, ctx);
4066
4288
  restParam = tsType ? `...${name}: ${tsType}[]` : `...${name}`;
4067
4289
  i += 3;
@@ -4078,7 +4300,7 @@ function transformParamList(node, ctx) {
4078
4300
  }
4079
4301
  if (child.name === "**" || getNodeText(child, ctx.source) === "**") {
4080
4302
  const nextChild = children[i + 1];
4081
- if (nextChild && nextChild.name === "VariableName") {
4303
+ if (nextChild?.name === "VariableName") {
4082
4304
  kwargsParam = getNodeText(nextChild, ctx.source);
4083
4305
  i += 2;
4084
4306
  continue;
@@ -4804,4 +5026,3 @@ export {
4804
5026
  /* v8 ignore next -- bare yield statement @preserve */
4805
5027
  /* v8 ignore next 2 -- fallback for future/unknown runtime functions @preserve */
4806
5028
  /* v8 ignore start -- async wrappers tested via CLI @preserve */
4807
- //# sourceMappingURL=chunk-MEHQCUVO.js.map
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-MEHQCUVO.js";
4
+ } from "../chunk-LNOL3BMB.js";
5
5
 
6
6
  // src/cli/index.ts
7
7
  import { parseArgs } from "util";
@@ -113,4 +113,3 @@ main().catch((error) => {
113
113
  console.error(`Unexpected error: ${String(error)}`);
114
114
  process.exit(1);
115
115
  });
116
- //# sourceMappingURL=index.js.map
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  transpile,
13
13
  transpileAsync,
14
14
  walkTree
15
- } from "./chunk-MEHQCUVO.js";
15
+ } from "./chunk-LNOL3BMB.js";
16
16
  export {
17
17
  debugTree,
18
18
  formatCode,
@@ -28,4 +28,3 @@ export {
28
28
  transpileAsync,
29
29
  walkTree
30
30
  };
31
- //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "python2ts",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
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": "1.0.2"
56
+ "pythonlib": "2.0.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "tsup": "^8.5.1",