@generaltranslation/python-extractor 0.2.19 → 0.2.21

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.
@@ -1,68 +1,56 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- const resolveCache = new Map();
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ //#region src/resolveImport.ts
4
+ const resolveCache = /* @__PURE__ */ new Map();
4
5
  /**
5
- * Resolves a Python import module path to a file path on disk.
6
- *
7
- * Handles:
8
- * - Relative imports: `.helpers` → sibling `helpers.py`
9
- * - Parent relative imports: `..utils` → parent dir `utils.py`
10
- * - Absolute imports: `utils` → `utils.py` in same/parent dirs
11
- * - Dotted paths: `myapp.utils` → `myapp/utils.py`
12
- */
13
- export function resolveImportPath(moduleName, currentFilePath) {
14
- const cacheKey = `${currentFilePath}::${moduleName}`;
15
- if (resolveCache.has(cacheKey)) {
16
- return resolveCache.get(cacheKey);
17
- }
18
- const result = doResolve(moduleName, currentFilePath);
19
- resolveCache.set(cacheKey, result);
20
- return result;
6
+ * Resolves a Python import module path to a file path on disk.
7
+ *
8
+ * Handles:
9
+ * - Relative imports: `.helpers` → sibling `helpers.py`
10
+ * - Parent relative imports: `..utils` → parent dir `utils.py`
11
+ * - Absolute imports: `utils` → `utils.py` in same/parent dirs
12
+ * - Dotted paths: `myapp.utils` → `myapp/utils.py`
13
+ */
14
+ function resolveImportPath(moduleName, currentFilePath) {
15
+ const cacheKey = `${currentFilePath}::${moduleName}`;
16
+ if (resolveCache.has(cacheKey)) return resolveCache.get(cacheKey);
17
+ const result = doResolve(moduleName, currentFilePath);
18
+ resolveCache.set(cacheKey, result);
19
+ return result;
21
20
  }
22
21
  function doResolve(moduleName, currentFilePath) {
23
- const currentDir = path.dirname(currentFilePath);
24
- // Relative import: starts with dots
25
- if (moduleName.startsWith('.')) {
26
- // Count leading dots
27
- let dotCount = 0;
28
- while (dotCount < moduleName.length && moduleName[dotCount] === '.') {
29
- dotCount++;
30
- }
31
- // Go up (dotCount - 1) directories from current dir
32
- let baseDir = currentDir;
33
- for (let i = 1; i < dotCount; i++) {
34
- baseDir = path.dirname(baseDir);
35
- }
36
- const remainder = moduleName.slice(dotCount);
37
- if (!remainder) {
38
- // Bare dot import (e.g., "from . import X") — resolve to __init__.py
39
- const initPath = path.join(baseDir, '__init__.py');
40
- if (fs.existsSync(initPath))
41
- return initPath;
42
- return null;
43
- }
44
- return resolveModulePath(baseDir, remainder);
45
- }
46
- // Absolute import: dotted or simple name
47
- return resolveModulePath(currentDir, moduleName);
22
+ const currentDir = path.dirname(currentFilePath);
23
+ if (moduleName.startsWith(".")) {
24
+ let dotCount = 0;
25
+ while (dotCount < moduleName.length && moduleName[dotCount] === ".") dotCount++;
26
+ let baseDir = currentDir;
27
+ for (let i = 1; i < dotCount; i++) baseDir = path.dirname(baseDir);
28
+ const remainder = moduleName.slice(dotCount);
29
+ if (!remainder) {
30
+ const initPath = path.join(baseDir, "__init__.py");
31
+ if (fs.existsSync(initPath)) return initPath;
32
+ return null;
33
+ }
34
+ return resolveModulePath(baseDir, remainder);
35
+ }
36
+ return resolveModulePath(currentDir, moduleName);
48
37
  }
49
38
  /**
50
- * Resolves a dotted module name (e.g. "myapp.utils") relative to a base dir.
51
- * Tries: baseDir/myapp/utils.py, then baseDir/myapp/utils/__init__.py
52
- */
39
+ * Resolves a dotted module name (e.g. "myapp.utils") relative to a base dir.
40
+ * Tries: baseDir/myapp/utils.py, then baseDir/myapp/utils/__init__.py
41
+ */
53
42
  function resolveModulePath(baseDir, moduleName) {
54
- const parts = moduleName.split('.');
55
- const filePath = path.join(baseDir, ...parts) + '.py';
56
- if (fs.existsSync(filePath)) {
57
- return filePath;
58
- }
59
- // Try as package: moduleName/__init__.py
60
- const initPath = path.join(baseDir, ...parts, '__init__.py');
61
- if (fs.existsSync(initPath)) {
62
- return initPath;
63
- }
64
- return null;
43
+ const parts = moduleName.split(".");
44
+ const filePath = path.join(baseDir, ...parts) + ".py";
45
+ if (fs.existsSync(filePath)) return filePath;
46
+ const initPath = path.join(baseDir, ...parts, "__init__.py");
47
+ if (fs.existsSync(initPath)) return initPath;
48
+ return null;
65
49
  }
66
- export function clearResolveCache() {
67
- resolveCache.clear();
50
+ function clearResolveCache() {
51
+ resolveCache.clear();
68
52
  }
53
+ //#endregion
54
+ export { clearResolveCache, resolveImportPath };
55
+
56
+ //# sourceMappingURL=resolveImport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveImport.js","names":[],"sources":["../src/resolveImport.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nconst resolveCache = new Map<string, string | null>();\n\n/**\n * Resolves a Python import module path to a file path on disk.\n *\n * Handles:\n * - Relative imports: `.helpers` → sibling `helpers.py`\n * - Parent relative imports: `..utils` → parent dir `utils.py`\n * - Absolute imports: `utils` → `utils.py` in same/parent dirs\n * - Dotted paths: `myapp.utils` → `myapp/utils.py`\n */\nexport function resolveImportPath(\n moduleName: string,\n currentFilePath: string\n): string | null {\n const cacheKey = `${currentFilePath}::${moduleName}`;\n if (resolveCache.has(cacheKey)) {\n return resolveCache.get(cacheKey)!;\n }\n\n const result = doResolve(moduleName, currentFilePath);\n resolveCache.set(cacheKey, result);\n return result;\n}\n\nfunction doResolve(moduleName: string, currentFilePath: string): string | null {\n const currentDir = path.dirname(currentFilePath);\n\n // Relative import: starts with dots\n if (moduleName.startsWith('.')) {\n // Count leading dots\n let dotCount = 0;\n while (dotCount < moduleName.length && moduleName[dotCount] === '.') {\n dotCount++;\n }\n\n // Go up (dotCount - 1) directories from current dir\n let baseDir = currentDir;\n for (let i = 1; i < dotCount; i++) {\n baseDir = path.dirname(baseDir);\n }\n\n const remainder = moduleName.slice(dotCount);\n if (!remainder) {\n // Bare dot import (e.g., \"from . import X\") — resolve to __init__.py\n const initPath = path.join(baseDir, '__init__.py');\n if (fs.existsSync(initPath)) return initPath;\n return null;\n }\n\n return resolveModulePath(baseDir, remainder);\n }\n\n // Absolute import: dotted or simple name\n return resolveModulePath(currentDir, moduleName);\n}\n\n/**\n * Resolves a dotted module name (e.g. \"myapp.utils\") relative to a base dir.\n * Tries: baseDir/myapp/utils.py, then baseDir/myapp/utils/__init__.py\n */\nfunction resolveModulePath(baseDir: string, moduleName: string): string | null {\n const parts = moduleName.split('.');\n const filePath = path.join(baseDir, ...parts) + '.py';\n\n if (fs.existsSync(filePath)) {\n return filePath;\n }\n\n // Try as package: moduleName/__init__.py\n const initPath = path.join(baseDir, ...parts, '__init__.py');\n if (fs.existsSync(initPath)) {\n return initPath;\n }\n\n return null;\n}\n\nexport function clearResolveCache(): void {\n resolveCache.clear();\n}\n"],"mappings":";;;AAGA,MAAM,+BAAe,IAAI,KAA4B;;;;;;;;;;AAWrD,SAAgB,kBACd,YACA,iBACe;CACf,MAAM,WAAW,GAAG,gBAAgB,IAAI;AACxC,KAAI,aAAa,IAAI,SAAS,CAC5B,QAAO,aAAa,IAAI,SAAS;CAGnC,MAAM,SAAS,UAAU,YAAY,gBAAgB;AACrD,cAAa,IAAI,UAAU,OAAO;AAClC,QAAO;;AAGT,SAAS,UAAU,YAAoB,iBAAwC;CAC7E,MAAM,aAAa,KAAK,QAAQ,gBAAgB;AAGhD,KAAI,WAAW,WAAW,IAAI,EAAE;EAE9B,IAAI,WAAW;AACf,SAAO,WAAW,WAAW,UAAU,WAAW,cAAc,IAC9D;EAIF,IAAI,UAAU;AACd,OAAK,IAAI,IAAI,GAAG,IAAI,UAAU,IAC5B,WAAU,KAAK,QAAQ,QAAQ;EAGjC,MAAM,YAAY,WAAW,MAAM,SAAS;AAC5C,MAAI,CAAC,WAAW;GAEd,MAAM,WAAW,KAAK,KAAK,SAAS,cAAc;AAClD,OAAI,GAAG,WAAW,SAAS,CAAE,QAAO;AACpC,UAAO;;AAGT,SAAO,kBAAkB,SAAS,UAAU;;AAI9C,QAAO,kBAAkB,YAAY,WAAW;;;;;;AAOlD,SAAS,kBAAkB,SAAiB,YAAmC;CAC7E,MAAM,QAAQ,WAAW,MAAM,IAAI;CACnC,MAAM,WAAW,KAAK,KAAK,SAAS,GAAG,MAAM,GAAG;AAEhD,KAAI,GAAG,WAAW,SAAS,CACzB,QAAO;CAIT,MAAM,WAAW,KAAK,KAAK,SAAS,GAAG,OAAO,cAAc;AAC5D,KAAI,GAAG,WAAW,SAAS,CACzB,QAAO;AAGT,QAAO;;AAGT,SAAgB,oBAA0B;AACxC,cAAa,OAAO"}
@@ -1,51 +1,37 @@
1
- // ===== Tree Construction ===== //
2
- // Used for derive / declare_var parsing
1
+ //#region src/stringNode.ts
3
2
  /**
4
- * Converts a StringNode tree into all possible string variants.
5
- * - TextNode → single string
6
- * - SequenceNode → cartesian product of all parts
7
- * - ChoiceNode → flattened branches (deduplicated)
8
- */
9
- export function nodeToStrings(node) {
10
- if (node === null) {
11
- return [];
12
- }
13
- if (node.type === 'text') {
14
- return [node.text];
15
- }
16
- if (node.type === 'sequence') {
17
- const partResults = node.nodes.map((n) => nodeToStrings(n));
18
- return cartesianProduct(partResults);
19
- }
20
- if (node.type === 'choice') {
21
- const allStrings = [];
22
- for (const branch of node.nodes) {
23
- allStrings.push(...nodeToStrings(branch));
24
- }
25
- return [...new Set(allStrings)]; // Deduplicate
26
- }
27
- return [];
3
+ * Converts a StringNode tree into all possible string variants.
4
+ * - TextNode → single string
5
+ * - SequenceNode → cartesian product of all parts
6
+ * - ChoiceNode → flattened branches (deduplicated)
7
+ */
8
+ function nodeToStrings(node) {
9
+ if (node === null) return [];
10
+ if (node.type === "text") return [node.text];
11
+ if (node.type === "sequence") return cartesianProduct(node.nodes.map((n) => nodeToStrings(n)));
12
+ if (node.type === "choice") {
13
+ const allStrings = [];
14
+ for (const branch of node.nodes) allStrings.push(...nodeToStrings(branch));
15
+ return [...new Set(allStrings)];
16
+ }
17
+ return [];
28
18
  }
29
19
  /**
30
- * Creates cartesian product of string arrays and concatenates them.
31
- * @example cartesianProduct([["Hello "], ["day", "night"]]) → ["Hello day", "Hello night"]
32
- */
20
+ * Creates cartesian product of string arrays and concatenates them.
21
+ * @example cartesianProduct([["Hello "], ["day", "night"]]) → ["Hello day", "Hello night"]
22
+ */
33
23
  function cartesianProduct(arrays) {
34
- if (arrays.length === 0) {
35
- return [];
36
- }
37
- if (arrays.length === 1) {
38
- return arrays[0];
39
- }
40
- let result = arrays[0];
41
- for (let i = 1; i < arrays.length; i++) {
42
- const newResult = [];
43
- for (const prev of result) {
44
- for (const curr of arrays[i]) {
45
- newResult.push(prev + curr);
46
- }
47
- }
48
- result = newResult;
49
- }
50
- return result;
24
+ if (arrays.length === 0) return [];
25
+ if (arrays.length === 1) return arrays[0];
26
+ let result = arrays[0];
27
+ for (let i = 1; i < arrays.length; i++) {
28
+ const newResult = [];
29
+ for (const prev of result) for (const curr of arrays[i]) newResult.push(prev + curr);
30
+ result = newResult;
31
+ }
32
+ return result;
51
33
  }
34
+ //#endregion
35
+ export { nodeToStrings };
36
+
37
+ //# sourceMappingURL=stringNode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stringNode.js","names":[],"sources":["../src/stringNode.ts"],"sourcesContent":["// ===== Tree Construction ===== //\n// Used for derive / declare_var parsing\n\ntype StringNode = StringTextNode | StringSequenceNode | StringChoiceNode;\n\ntype StringTextNode = {\n type: 'text';\n text: string;\n};\n\ntype StringSequenceNode = {\n type: 'sequence';\n nodes: StringNode[];\n};\n\ntype StringChoiceNode = {\n type: 'choice';\n nodes: StringNode[];\n};\n\nexport type {\n StringNode,\n StringTextNode,\n StringSequenceNode,\n StringChoiceNode,\n};\n\n/**\n * Converts a StringNode tree into all possible string variants.\n * - TextNode → single string\n * - SequenceNode → cartesian product of all parts\n * - ChoiceNode → flattened branches (deduplicated)\n */\nexport function nodeToStrings(node: StringNode | null): string[] {\n if (node === null) {\n return [];\n }\n\n if (node.type === 'text') {\n return [node.text];\n }\n\n if (node.type === 'sequence') {\n const partResults: string[][] = node.nodes.map((n) => nodeToStrings(n));\n return cartesianProduct(partResults);\n }\n\n if (node.type === 'choice') {\n const allStrings: string[] = [];\n for (const branch of node.nodes) {\n allStrings.push(...nodeToStrings(branch));\n }\n return [...new Set(allStrings)]; // Deduplicate\n }\n\n return [];\n}\n\n/**\n * Creates cartesian product of string arrays and concatenates them.\n * @example cartesianProduct([[\"Hello \"], [\"day\", \"night\"]]) → [\"Hello day\", \"Hello night\"]\n */\nfunction cartesianProduct(arrays: string[][]): string[] {\n if (arrays.length === 0) {\n return [];\n }\n\n if (arrays.length === 1) {\n return arrays[0];\n }\n\n let result = arrays[0];\n\n for (let i = 1; i < arrays.length; i++) {\n const newResult: string[] = [];\n for (const prev of result) {\n for (const curr of arrays[i]) {\n newResult.push(prev + curr);\n }\n }\n result = newResult;\n }\n\n return result;\n}\n"],"mappings":";;;;;;;AAiCA,SAAgB,cAAc,MAAmC;AAC/D,KAAI,SAAS,KACX,QAAO,EAAE;AAGX,KAAI,KAAK,SAAS,OAChB,QAAO,CAAC,KAAK,KAAK;AAGpB,KAAI,KAAK,SAAS,WAEhB,QAAO,iBADyB,KAAK,MAAM,KAAK,MAAM,cAAc,EAAE,CACnC,CAAC;AAGtC,KAAI,KAAK,SAAS,UAAU;EAC1B,MAAM,aAAuB,EAAE;AAC/B,OAAK,MAAM,UAAU,KAAK,MACxB,YAAW,KAAK,GAAG,cAAc,OAAO,CAAC;AAE3C,SAAO,CAAC,GAAG,IAAI,IAAI,WAAW,CAAC;;AAGjC,QAAO,EAAE;;;;;;AAOX,SAAS,iBAAiB,QAA8B;AACtD,KAAI,OAAO,WAAW,EACpB,QAAO,EAAE;AAGX,KAAI,OAAO,WAAW,EACpB,QAAO,OAAO;CAGhB,IAAI,SAAS,OAAO;AAEpB,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;EACtC,MAAM,YAAsB,EAAE;AAC9B,OAAK,MAAM,QAAQ,OACjB,MAAK,MAAM,QAAQ,OAAO,GACxB,WAAU,KAAK,OAAO,KAAK;AAG/B,WAAS;;AAGX,QAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@generaltranslation/python-extractor",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "description": "Python source code extraction for General Translation",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -38,6 +38,7 @@
38
38
  ],
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.13.5",
41
+ "tsdown": "^0.21.10",
41
42
  "typescript": "^5.9.2",
42
43
  "vitest": "^3.2.4"
43
44
  },
@@ -47,11 +48,13 @@
47
48
  "dependencies": {
48
49
  "tree-sitter-python": "^0.25.0",
49
50
  "web-tree-sitter": "^0.26.6",
50
- "generaltranslation": "8.2.13"
51
+ "generaltranslation": "8.2.15"
51
52
  },
52
53
  "scripts": {
53
- "build": "tsc",
54
- "build:watch": "tsc --watch",
54
+ "emit-types": "sh ../../scripts/emit-types.sh",
55
+ "transpile": "tsdown && pnpm run emit-types",
56
+ "build": "pnpm run transpile",
57
+ "build:watch": "tsdown --watch",
55
58
  "build:clean": "sh ../../scripts/clean.sh && pnpm run build",
56
59
  "build:release": "pnpm run build:clean",
57
60
  "format": "oxfmt src",