pynect 0.0.0 → 0.2.1

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.
Files changed (191) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +503 -2
  3. package/SECURITY.md +34 -0
  4. package/binding.gyp +67 -0
  5. package/dist/cli/codegen.d.ts +3 -0
  6. package/dist/cli/codegen.d.ts.map +1 -0
  7. package/dist/cli/codegen.js +543 -0
  8. package/dist/cli/codegen.js.map +1 -0
  9. package/dist/cli/sync.d.ts +3 -0
  10. package/dist/cli/sync.d.ts.map +1 -0
  11. package/dist/cli/sync.js +47 -0
  12. package/dist/cli/sync.js.map +1 -0
  13. package/dist/config/project.d.ts +113 -0
  14. package/dist/config/project.d.ts.map +1 -0
  15. package/dist/config/project.js +344 -0
  16. package/dist/config/project.js.map +1 -0
  17. package/dist/core/isolated-worker.d.ts +39 -0
  18. package/dist/core/isolated-worker.d.ts.map +1 -0
  19. package/dist/core/isolated-worker.js +178 -0
  20. package/dist/core/isolated-worker.js.map +1 -0
  21. package/dist/core/py-callable.d.ts +67 -0
  22. package/dist/core/py-callable.d.ts.map +1 -0
  23. package/dist/core/py-callable.js +104 -0
  24. package/dist/core/py-callable.js.map +1 -0
  25. package/dist/core/py-context.d.ts +76 -0
  26. package/dist/core/py-context.d.ts.map +1 -0
  27. package/dist/core/py-context.js +239 -0
  28. package/dist/core/py-context.js.map +1 -0
  29. package/dist/core/py-iterator.d.ts +84 -0
  30. package/dist/core/py-iterator.d.ts.map +1 -0
  31. package/dist/core/py-iterator.js +243 -0
  32. package/dist/core/py-iterator.js.map +1 -0
  33. package/dist/core/py-module.d.ts +53 -0
  34. package/dist/core/py-module.d.ts.map +1 -0
  35. package/dist/core/py-module.js +162 -0
  36. package/dist/core/py-module.js.map +1 -0
  37. package/dist/core/py-proxy.d.ts +75 -0
  38. package/dist/core/py-proxy.d.ts.map +1 -0
  39. package/dist/core/py-proxy.js +563 -0
  40. package/dist/core/py-proxy.js.map +1 -0
  41. package/dist/core/py-runtime.d.ts +113 -0
  42. package/dist/core/py-runtime.d.ts.map +1 -0
  43. package/dist/core/py-runtime.js +528 -0
  44. package/dist/core/py-runtime.js.map +1 -0
  45. package/dist/env/executables.d.ts +3 -0
  46. package/dist/env/executables.d.ts.map +1 -0
  47. package/dist/env/executables.js +14 -0
  48. package/dist/env/executables.js.map +1 -0
  49. package/dist/env/package-installer.d.ts +232 -0
  50. package/dist/env/package-installer.d.ts.map +1 -0
  51. package/dist/env/package-installer.js +615 -0
  52. package/dist/env/package-installer.js.map +1 -0
  53. package/dist/env/project-environment.d.ts +64 -0
  54. package/dist/env/project-environment.d.ts.map +1 -0
  55. package/dist/env/project-environment.js +388 -0
  56. package/dist/env/project-environment.js.map +1 -0
  57. package/dist/env/pyfig-adapter.d.ts +38 -0
  58. package/dist/env/pyfig-adapter.d.ts.map +1 -0
  59. package/dist/env/pyfig-adapter.js +10 -0
  60. package/dist/env/pyfig-adapter.js.map +1 -0
  61. package/dist/env/python-detector.d.ts +48 -0
  62. package/dist/env/python-detector.d.ts.map +1 -0
  63. package/dist/env/python-detector.js +182 -0
  64. package/dist/env/python-detector.js.map +1 -0
  65. package/dist/env/python-provisioner.d.ts +16 -0
  66. package/dist/env/python-provisioner.d.ts.map +1 -0
  67. package/dist/env/python-provisioner.js +42 -0
  68. package/dist/env/python-provisioner.js.map +1 -0
  69. package/dist/env/venv-manager.d.ts +56 -0
  70. package/dist/env/venv-manager.d.ts.map +1 -0
  71. package/dist/env/venv-manager.js +160 -0
  72. package/dist/env/venv-manager.js.map +1 -0
  73. package/dist/index.d.ts +182 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +394 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/native/native-addon-loader.d.ts +13 -0
  78. package/dist/native/native-addon-loader.d.ts.map +1 -0
  79. package/dist/native/native-addon-loader.js +171 -0
  80. package/dist/native/native-addon-loader.js.map +1 -0
  81. package/dist/plugins/builtin/numpy-plugin.d.ts +17 -0
  82. package/dist/plugins/builtin/numpy-plugin.d.ts.map +1 -0
  83. package/dist/plugins/builtin/numpy-plugin.js +41 -0
  84. package/dist/plugins/builtin/numpy-plugin.js.map +1 -0
  85. package/dist/plugins/builtin/pandas-plugin.d.ts +19 -0
  86. package/dist/plugins/builtin/pandas-plugin.d.ts.map +1 -0
  87. package/dist/plugins/builtin/pandas-plugin.js +57 -0
  88. package/dist/plugins/builtin/pandas-plugin.js.map +1 -0
  89. package/dist/plugins/builtin/torch-plugin.d.ts +23 -0
  90. package/dist/plugins/builtin/torch-plugin.d.ts.map +1 -0
  91. package/dist/plugins/builtin/torch-plugin.js +50 -0
  92. package/dist/plugins/builtin/torch-plugin.js.map +1 -0
  93. package/dist/plugins/index.d.ts +7 -0
  94. package/dist/plugins/index.d.ts.map +1 -0
  95. package/dist/plugins/index.js +12 -0
  96. package/dist/plugins/index.js.map +1 -0
  97. package/dist/plugins/plugin-manager.d.ts +26 -0
  98. package/dist/plugins/plugin-manager.d.ts.map +1 -0
  99. package/dist/plugins/plugin-manager.js +174 -0
  100. package/dist/plugins/plugin-manager.js.map +1 -0
  101. package/dist/plugins/plugin.interface.d.ts +41 -0
  102. package/dist/plugins/plugin.interface.d.ts.map +1 -0
  103. package/dist/plugins/plugin.interface.js +12 -0
  104. package/dist/plugins/plugin.interface.js.map +1 -0
  105. package/dist/serialization/data-frame-bridge.d.ts +141 -0
  106. package/dist/serialization/data-frame-bridge.d.ts.map +1 -0
  107. package/dist/serialization/data-frame-bridge.js +355 -0
  108. package/dist/serialization/data-frame-bridge.js.map +1 -0
  109. package/dist/serialization/msg-pack-serializer.d.ts +45 -0
  110. package/dist/serialization/msg-pack-serializer.d.ts.map +1 -0
  111. package/dist/serialization/msg-pack-serializer.js +242 -0
  112. package/dist/serialization/msg-pack-serializer.js.map +1 -0
  113. package/dist/serialization/numpy-bridge.d.ts +96 -0
  114. package/dist/serialization/numpy-bridge.d.ts.map +1 -0
  115. package/dist/serialization/numpy-bridge.js +323 -0
  116. package/dist/serialization/numpy-bridge.js.map +1 -0
  117. package/dist/serialization/serializer.d.ts +78 -0
  118. package/dist/serialization/serializer.d.ts.map +1 -0
  119. package/dist/serialization/serializer.js +281 -0
  120. package/dist/serialization/serializer.js.map +1 -0
  121. package/dist/types/addon.d.ts +131 -0
  122. package/dist/types/addon.d.ts.map +1 -0
  123. package/dist/types/addon.js +32 -0
  124. package/dist/types/addon.js.map +1 -0
  125. package/dist/types/config.d.ts +236 -0
  126. package/dist/types/config.d.ts.map +1 -0
  127. package/dist/types/config.js +61 -0
  128. package/dist/types/config.js.map +1 -0
  129. package/dist/types/index.d.ts +10 -0
  130. package/dist/types/index.d.ts.map +1 -0
  131. package/dist/types/index.js +12 -0
  132. package/dist/types/index.js.map +1 -0
  133. package/dist/types/python.d.ts +235 -0
  134. package/dist/types/python.d.ts.map +1 -0
  135. package/dist/types/python.js +7 -0
  136. package/dist/types/python.js.map +1 -0
  137. package/dist/utils/error-translator.d.ts +83 -0
  138. package/dist/utils/error-translator.d.ts.map +1 -0
  139. package/dist/utils/error-translator.js +210 -0
  140. package/dist/utils/error-translator.js.map +1 -0
  141. package/dist/utils/locking.d.ts +3 -0
  142. package/dist/utils/locking.d.ts.map +1 -0
  143. package/dist/utils/locking.js +10 -0
  144. package/dist/utils/locking.js.map +1 -0
  145. package/dist/utils/logger.d.ts +27 -0
  146. package/dist/utils/logger.d.ts.map +1 -0
  147. package/dist/utils/logger.js +115 -0
  148. package/dist/utils/logger.js.map +1 -0
  149. package/dist/utils/memory-monitor.d.ts +43 -0
  150. package/dist/utils/memory-monitor.d.ts.map +1 -0
  151. package/dist/utils/memory-monitor.js +143 -0
  152. package/dist/utils/memory-monitor.js.map +1 -0
  153. package/package.json +93 -17
  154. package/prebuilds/darwin-arm64/pynect-prebuild.json +8 -0
  155. package/prebuilds/darwin-arm64/pynect_addon.node +0 -0
  156. package/prebuilds/darwin-x64/pynect-prebuild.json +8 -0
  157. package/prebuilds/darwin-x64/pynect_addon.node +0 -0
  158. package/prebuilds/linux-arm64/pynect-prebuild.json +9 -0
  159. package/prebuilds/linux-arm64/pynect_addon.node +0 -0
  160. package/prebuilds/linux-x64/pynect-prebuild.json +9 -0
  161. package/prebuilds/linux-x64/pynect_addon.node +0 -0
  162. package/prebuilds/win32-arm64/pynect-prebuild.json +8 -0
  163. package/prebuilds/win32-arm64/pynect_addon.node +0 -0
  164. package/prebuilds/win32-x64/pynect-prebuild.json +8 -0
  165. package/prebuilds/win32-x64/pynect_addon.node +0 -0
  166. package/python/ast_inspector.py +248 -0
  167. package/python/error_handler.py +432 -0
  168. package/python/isolated_worker.py +94 -0
  169. package/python/pynect_dispatcher.py +382 -0
  170. package/python/pynect_runtime.py +574 -0
  171. package/python/serializer.py +373 -0
  172. package/python/type_inspector.py +315 -0
  173. package/scripts/build-native.js +50 -0
  174. package/scripts/cli.js +21 -0
  175. package/scripts/ensure-native.js +85 -0
  176. package/scripts/postinstall.js +40 -0
  177. package/scripts/pyfig.js +128 -0
  178. package/scripts/python-provisioner.js +23 -0
  179. package/scripts/smoke-python-boundary.js +103 -0
  180. package/src/native/gil_guard.cpp +25 -0
  181. package/src/native/gil_guard.h +174 -0
  182. package/src/native/native-addon-loader.ts +218 -0
  183. package/src/native/pynect_addon.cpp +942 -0
  184. package/src/native/python_bridge.cpp +904 -0
  185. package/src/native/python_bridge.h +263 -0
  186. package/src/native/thread_pool.cpp +375 -0
  187. package/src/native/thread_pool.h +185 -0
  188. package/src/native/type_converter.cpp +906 -0
  189. package/src/native/type_converter.h +271 -0
  190. package/index.d.ts +0 -3
  191. package/index.js +0 -3
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ /**
3
+ * Compatibility facade for callers that previously enumerated host Python
4
+ * installations. Pynect now exposes only its Pyfig-selected repository venv.
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.PythonVersionError = exports.PythonNotFoundError = exports.PythonDetector = void 0;
11
+ const path_1 = __importDefault(require("path"));
12
+ const logger_1 = require("../utils/logger");
13
+ const pyfig_adapter_1 = require("./pyfig-adapter");
14
+ const executables_1 = require("./executables");
15
+ const logger = new logger_1.Logger('PythonDetector');
16
+ const PROBE_SCRIPT = `
17
+ import json, platform, sys
18
+ print(json.dumps({
19
+ "executable": sys.executable,
20
+ "base_executable": getattr(sys, "_base_executable", sys.executable),
21
+ "version": ".".join(map(str, sys.version_info[:3])),
22
+ "major": sys.version_info.major,
23
+ "minor": sys.version_info.minor,
24
+ "patch": sys.version_info.micro,
25
+ "prefix": sys.prefix,
26
+ "is_venv": sys.prefix != getattr(sys, "base_prefix", sys.prefix),
27
+ "platform": sys.platform,
28
+ "arch": platform.machine(),
29
+ }))
30
+ `.trim();
31
+ class PythonDetector {
32
+ options;
33
+ constructor(options = {}) {
34
+ this.options = {
35
+ minVersion: options.minVersion ?? [3, 10],
36
+ pythonPath: options.pythonPath ?? '',
37
+ timeout: options.timeout ?? 10_000,
38
+ explicitOnly: options.explicitOnly ?? false,
39
+ requiredModules: options.requiredModules ?? [],
40
+ projectRoot: options.projectRoot,
41
+ };
42
+ }
43
+ async detect() {
44
+ try {
45
+ const { python } = await (0, pyfig_adapter_1.ensurePynectPython)(this.selectionOptions());
46
+ const info = toPythonInfo(python);
47
+ if (!this.isCompatible(info)) {
48
+ throw new PythonVersionError(info.version, this.options.minVersion.join('.'));
49
+ }
50
+ const missing = this.checkModules(info.executable, this.options.requiredModules);
51
+ if (missing.length > 0) {
52
+ throw new PythonNotFoundError(`Repository Python ${info.executable} is missing modules: ${missing.join(', ')}.`);
53
+ }
54
+ logger.info(`PythonDetector: using repository venv ${info.executable} (${info.version})`);
55
+ return info;
56
+ }
57
+ catch (error) {
58
+ if (error instanceof PythonNotFoundError || error instanceof PythonVersionError)
59
+ throw error;
60
+ throw new PythonNotFoundError(`Could not prepare repository Python >= ${this.options.minVersion.join('.')}: ` +
61
+ `${errorMessage(error)}`);
62
+ }
63
+ }
64
+ /** Probe through Pyfig; never executes the supplied interpreter directly. */
65
+ probe(executablePath) {
66
+ if (!executablePath)
67
+ return null;
68
+ const client = (0, pyfig_adapter_1.createPynectPyfig)(this.selectionOptions(executablePath));
69
+ const result = client.pythonSync(['-c', PROBE_SCRIPT], {
70
+ encoding: 'utf8',
71
+ timeout: this.options.timeout,
72
+ maxBuffer: 1024 * 1024,
73
+ env: { ...process.env, PYTHONDONTWRITEBYTECODE: '1' },
74
+ });
75
+ const stdout = outputText(result.stdout);
76
+ if (result.status !== 0 || result.error || !stdout.trim())
77
+ return null;
78
+ try {
79
+ const raw = JSON.parse(stdout.trim());
80
+ if (path_1.default.isAbsolute(executablePath)) {
81
+ const requested = normalizePath(executablePath);
82
+ if (requested !== normalizePath(raw.executable) &&
83
+ requested !== normalizePath(raw.base_executable))
84
+ return null;
85
+ }
86
+ return probeToPythonInfo(raw);
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ }
92
+ isCompatible(info) {
93
+ const [major, minor] = this.options.minVersion;
94
+ return info.major > major || (info.major === major && info.minor >= minor);
95
+ }
96
+ checkModules(executable, modules) {
97
+ if (modules.length === 0)
98
+ return [];
99
+ const invalid = modules.filter(module => !(0, executables_1.isPythonModuleName)(module));
100
+ if (invalid.length > 0) {
101
+ throw new TypeError(`Invalid Python module name: ${invalid.join(', ')}`);
102
+ }
103
+ const script = modules
104
+ .map(module => `try:\n import ${module}\nexcept ImportError:\n print("MISSING:${module}")`)
105
+ .join('\n');
106
+ const client = (0, pyfig_adapter_1.createPynectPyfig)(this.selectionOptions(executable));
107
+ const result = client.pythonSync(['-c', script], { encoding: 'utf8', timeout: this.options.timeout, maxBuffer: 1024 * 256 });
108
+ if (result.status !== 0 || result.error)
109
+ return [...modules];
110
+ return outputText(result.stdout)
111
+ .split(/\r?\n/u)
112
+ .map(line => line.match(/^MISSING:(.+)$/u)?.[1])
113
+ .filter((module) => Boolean(module));
114
+ }
115
+ /** The fixed-root policy intentionally exposes one selected interpreter. */
116
+ async listAll() {
117
+ return [await this.detect()];
118
+ }
119
+ selectionOptions(pythonPath = this.options.pythonPath) {
120
+ const [major, minor] = this.options.minVersion;
121
+ return {
122
+ pythonPath,
123
+ pythonRange: `>=${major}.${minor}.0 <4.0.0`,
124
+ projectRoot: this.options.projectRoot,
125
+ autoInstallPython: !this.options.explicitOnly,
126
+ autoInstallUv: !this.options.explicitOnly,
127
+ autoCreateVirtualEnvironment: !this.options.explicitOnly,
128
+ };
129
+ }
130
+ }
131
+ exports.PythonDetector = PythonDetector;
132
+ function probeToPythonInfo(raw) {
133
+ return {
134
+ executable: raw.executable,
135
+ version: raw.version,
136
+ major: raw.major,
137
+ minor: raw.minor,
138
+ patch: raw.patch,
139
+ prefix: raw.prefix,
140
+ isVirtualenv: raw.is_venv,
141
+ platform: raw.platform,
142
+ arch: raw.arch,
143
+ };
144
+ }
145
+ function toPythonInfo(python) {
146
+ return {
147
+ executable: python.executable,
148
+ version: python.version,
149
+ major: python.major,
150
+ minor: python.minor,
151
+ patch: python.patch,
152
+ prefix: python.prefix,
153
+ isVirtualenv: python.virtualEnvironment !== null,
154
+ platform: process.platform,
155
+ arch: process.arch,
156
+ };
157
+ }
158
+ function normalizePath(value) {
159
+ const resolved = path_1.default.resolve(value);
160
+ return process.platform === 'win32' ? resolved.toLowerCase() : resolved;
161
+ }
162
+ function outputText(value) {
163
+ return typeof value === 'string' ? value : value?.toString('utf8') ?? '';
164
+ }
165
+ function errorMessage(error) {
166
+ return error instanceof Error ? error.message : String(error);
167
+ }
168
+ class PythonNotFoundError extends Error {
169
+ constructor(message) {
170
+ super(message);
171
+ this.name = 'PythonNotFoundError';
172
+ }
173
+ }
174
+ exports.PythonNotFoundError = PythonNotFoundError;
175
+ class PythonVersionError extends Error {
176
+ constructor(found, required) {
177
+ super(`Python ${found} is below the minimum required version ${required}.`);
178
+ this.name = 'PythonVersionError';
179
+ }
180
+ }
181
+ exports.PythonVersionError = PythonVersionError;
182
+ //# sourceMappingURL=python-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-detector.js","sourceRoot":"","sources":["../../src/env/python-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { PythonInfo } from './python-detector';
2
+ export interface PythonProvisionerOptions {
3
+ minVersion?: [number, number];
4
+ managedPython?: string;
5
+ uvVersion?: string;
6
+ autoInstall?: boolean;
7
+ pythonPath?: string;
8
+ projectRoot?: string;
9
+ }
10
+ /** Compatibility wrapper around Pynect's centralized Pyfig environment selection. */
11
+ export declare class PythonProvisioner {
12
+ private readonly options;
13
+ constructor(options?: PythonProvisionerOptions);
14
+ ensurePython(): Promise<PythonInfo>;
15
+ }
16
+ //# sourceMappingURL=python-provisioner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-provisioner.d.ts","sourceRoot":"","sources":["../../src/env/python-provisioner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAOpD,MAAM,WAAW,wBAAwB;IACvC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qFAAqF;AACrF,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,wBAA6B;IAE7D,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC;CAgB1C"}
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PythonProvisioner = void 0;
4
+ const pyfig_adapter_1 = require("./pyfig-adapter");
5
+ /** Compatibility wrapper around Pynect's centralized Pyfig environment selection. */
6
+ class PythonProvisioner {
7
+ options;
8
+ constructor(options = {}) {
9
+ this.options = options;
10
+ }
11
+ async ensurePython() {
12
+ const [major, minor] = this.options.minVersion ?? [3, 10];
13
+ const selection = {
14
+ autoInstallPython: this.options.autoInstall,
15
+ managedPython: this.options.managedPython,
16
+ pythonPath: this.options.pythonPath,
17
+ pythonRange: `>=${major}.${minor}.0 <4.0.0`,
18
+ projectRoot: this.options.projectRoot,
19
+ uvVersion: this.options.uvVersion,
20
+ };
21
+ const { python } = await (0, pyfig_adapter_1.ensurePynectPython)(selection);
22
+ if (python.major < major || (python.major === major && python.minor < minor)) {
23
+ throw new Error(`Python ${python.version} does not satisfy >=${major}.${minor}.`);
24
+ }
25
+ return toLegacyPythonInfo(python);
26
+ }
27
+ }
28
+ exports.PythonProvisioner = PythonProvisioner;
29
+ function toLegacyPythonInfo(python) {
30
+ return {
31
+ executable: python.executable,
32
+ version: python.version,
33
+ major: python.major,
34
+ minor: python.minor,
35
+ patch: python.patch,
36
+ prefix: python.prefix,
37
+ isVirtualenv: python.virtualEnvironment !== null,
38
+ platform: process.platform,
39
+ arch: process.arch,
40
+ };
41
+ }
42
+ //# sourceMappingURL=python-provisioner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-provisioner.js","sourceRoot":"","sources":["../../src/env/python-provisioner.ts"],"names":[],"mappings":";;;AACA,mDAIyB;AAWzB,qFAAqF;AACrF,MAAa,iBAAiB;IACC;IAA7B,YAA6B,UAAoC,EAAE;QAAtC,YAAO,GAAP,OAAO,CAA+B;IAAG,CAAC;IAEvE,KAAK,CAAC,YAAY;QAChB,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAwB;YACrC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;YAC3C,aAAa,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa;YACzC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU;YACnC,WAAW,EAAE,KAAK,KAAK,IAAI,KAAK,WAAW;YAC3C,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;YACrC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;SAClC,CAAC;QACF,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAA,kCAAkB,EAAC,SAAS,CAAC,CAAC;QACvD,IAAI,MAAM,CAAC,KAAK,GAAG,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC;YAC7E,MAAM,IAAI,KAAK,CAAC,UAAU,MAAM,CAAC,OAAO,uBAAuB,KAAK,IAAI,KAAK,GAAG,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;CACF;AAnBD,8CAmBC;AAED,SAAS,kBAAkB,CAAC,MAAsB;IAChD,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,YAAY,EAAE,MAAM,CAAC,kBAAkB,KAAK,IAAI;QAChD,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,56 @@
1
+ import type { VirtualenvConfig } from '../types/config';
2
+ export interface VenvState {
3
+ createdAt: number;
4
+ pythonVersion: string;
5
+ installedPackages: string[];
6
+ lastInstallAt: number;
7
+ }
8
+ export interface VenvSetupResult {
9
+ pythonExecutable: string;
10
+ /** The package-manager executable selected by Pyfig (uv or the venv Python). */
11
+ pipExecutable: string;
12
+ created: boolean;
13
+ packagesInstalled: boolean;
14
+ }
15
+ export interface VenvManagerOptions {
16
+ virtualenv: VirtualenvConfig;
17
+ basePython?: string;
18
+ installTimeout?: number;
19
+ /** Retained for API compatibility; Pyfig decides whether pip needs bootstrapping. */
20
+ skipPipUpgrade?: boolean;
21
+ }
22
+ /**
23
+ * Compatibility facade for the historical VenvManager API.
24
+ * Environment creation and package execution are delegated to Pyfig so Pynect
25
+ * cannot drift onto a different interpreter or standalone pip executable.
26
+ */
27
+ export declare class VenvManager {
28
+ private readonly config;
29
+ private readonly basePython;
30
+ private readonly installTimeout;
31
+ private readonly projectRoot;
32
+ private readonly configuredPath?;
33
+ private venvPath;
34
+ private statePath;
35
+ private selectedPython?;
36
+ constructor(options: VenvManagerOptions);
37
+ setup(): Promise<VenvSetupResult>;
38
+ install(packages: string[]): Promise<void>;
39
+ getMissingPackages(): string[];
40
+ get pythonExecutable(): string;
41
+ isValid(): boolean;
42
+ destroy(): void;
43
+ listInstalled(): string[];
44
+ private installer;
45
+ private assertSelectedEnvironment;
46
+ private updateState;
47
+ private loadState;
48
+ }
49
+ export declare class VenvCreationError extends Error {
50
+ constructor(message: string);
51
+ }
52
+ export declare class PackageInstallError extends Error {
53
+ readonly packages: string[];
54
+ constructor(packages: string[], detail: string);
55
+ }
56
+ //# sourceMappingURL=venv-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"venv-manager.d.ts","sourceRoot":"","sources":["../../src/env/venv-manager.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAYxD,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gFAAgF;IAChF,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qFAAqF;IACrF,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAIrB;IACF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,cAAc,CAAC,CAAiB;gBAE5B,OAAO,EAAE,kBAAkB;IAqBjC,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC;IA6BjC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYhD,kBAAkB,IAAI,MAAM,EAAE;IAI9B,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,OAAO,IAAI,OAAO;IAKlB,OAAO,IAAI,IAAI;IAOf,aAAa,IAAI,MAAM,EAAE;IAIzB,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,yBAAyB;IAWjC,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,SAAS;CAOlB;AAkBD,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;gBAEhB,QAAQ,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM;CAK/C"}
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PackageInstallError = exports.VenvCreationError = exports.VenvManager = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const logger_1 = require("../utils/logger");
10
+ const package_installer_1 = require("./package-installer");
11
+ const pyfig_adapter_1 = require("./pyfig-adapter");
12
+ const logger = new logger_1.Logger('VenvManager');
13
+ const STATE_FILENAME = '.pynect-venv-state.json';
14
+ /**
15
+ * Compatibility facade for the historical VenvManager API.
16
+ * Environment creation and package execution are delegated to Pyfig so Pynect
17
+ * cannot drift onto a different interpreter or standalone pip executable.
18
+ */
19
+ class VenvManager {
20
+ config;
21
+ basePython;
22
+ installTimeout;
23
+ projectRoot;
24
+ configuredPath;
25
+ venvPath;
26
+ statePath;
27
+ selectedPython;
28
+ constructor(options) {
29
+ this.config = {
30
+ ...options.virtualenv,
31
+ packages: options.virtualenv.packages ?? [],
32
+ autoInstall: options.virtualenv.autoInstall ?? false,
33
+ pipArgs: options.virtualenv.pipArgs ?? [],
34
+ };
35
+ this.basePython = options.basePython ?? '';
36
+ this.installTimeout = options.installTimeout ?? 300_000;
37
+ this.configuredPath = this.config.path ? path_1.default.resolve(this.config.path) : undefined;
38
+ this.projectRoot = (0, pyfig_adapter_1.pynectProjectRoot)();
39
+ const rootEnvironment = path_1.default.join(this.projectRoot, '.venv');
40
+ this.venvPath = this.configuredPath ?? (fs_1.default.existsSync(rootEnvironment)
41
+ ? rootEnvironment
42
+ : path_1.default.join(this.projectRoot, 'node_modules', '.pyfig', 'venv'));
43
+ this.statePath = path_1.default.join(this.venvPath, STATE_FILENAME);
44
+ }
45
+ async setup() {
46
+ const existed = this.isValid();
47
+ const { environment } = await (0, pyfig_adapter_1.ensurePynectEnvironment)({
48
+ projectRoot: this.projectRoot,
49
+ pythonPath: this.configuredPath && this.isValid()
50
+ ? venvPython(this.configuredPath)
51
+ : this.basePython,
52
+ });
53
+ this.selectedPython = environment.python;
54
+ this.assertSelectedEnvironment(environment.python);
55
+ this.venvPath = environment.python.virtualEnvironment;
56
+ this.statePath = path_1.default.join(this.venvPath, STATE_FILENAME);
57
+ if (this.config.autoInstall && this.config.packages.length > 0) {
58
+ throw new Error('VenvManager auto-install is no longer supported. Declare package.json ' +
59
+ 'pynect.project.dependencies and run "pynect sync".');
60
+ }
61
+ logger.info(`VenvManager: ready: ${environment.python.executable}`);
62
+ return {
63
+ pythonExecutable: environment.python.executable,
64
+ pipExecutable: environment.uv.executable,
65
+ created: !existed,
66
+ packagesInstalled: false,
67
+ };
68
+ }
69
+ async install(packages) {
70
+ const installer = this.installer();
71
+ const result = await installer.install(packages);
72
+ if (!result.success) {
73
+ throw new PackageInstallError(packages, result.failed.map(item => `${item.spec}: ${item.error}`).join('; '));
74
+ }
75
+ this.updateState(installer);
76
+ }
77
+ getMissingPackages() {
78
+ return this.installer().getMissing(this.config.packages);
79
+ }
80
+ get pythonExecutable() {
81
+ return this.selectedPython?.executable ?? venvPython(this.venvPath);
82
+ }
83
+ isValid() {
84
+ return fs_1.default.existsSync(path_1.default.join(this.venvPath, 'pyvenv.cfg')) &&
85
+ fs_1.default.existsSync(venvPython(this.venvPath));
86
+ }
87
+ destroy() {
88
+ if (fs_1.default.existsSync(this.venvPath)) {
89
+ fs_1.default.rmSync(this.venvPath, { recursive: true, force: true });
90
+ logger.info(`VenvManager: destroyed venv at ${this.venvPath}`);
91
+ }
92
+ }
93
+ listInstalled() {
94
+ return this.loadState()?.installedPackages ?? [];
95
+ }
96
+ installer() {
97
+ if (!this.isValid()) {
98
+ throw new Error(`VenvManager: venv does not exist at ${this.venvPath}`);
99
+ }
100
+ return new package_installer_1.PackageInstaller({
101
+ pythonExecutable: this.pythonExecutable,
102
+ cwd: this.projectRoot,
103
+ indexUrl: this.config.pipIndexUrl,
104
+ timeoutMs: this.installTimeout,
105
+ });
106
+ }
107
+ assertSelectedEnvironment(python) {
108
+ if (!python.virtualEnvironment) {
109
+ throw new Error(`Pyfig selected ${python.executable} without a virtual environment.`);
110
+ }
111
+ if (this.configuredPath && !pathsEqual(python.virtualEnvironment, this.configuredPath)) {
112
+ throw new Error(`Pyfig selected ${python.virtualEnvironment}; expected ${this.configuredPath}.`);
113
+ }
114
+ }
115
+ updateState(installer) {
116
+ const state = {
117
+ createdAt: this.loadState()?.createdAt ?? Date.now(),
118
+ pythonVersion: this.selectedPython?.version ?? 'unknown',
119
+ installedPackages: installer.listInstalled().map(item => `${item.name}==${item.version}`),
120
+ lastInstallAt: Date.now(),
121
+ };
122
+ fs_1.default.writeFileSync(this.statePath, JSON.stringify(state, null, 2), 'utf8');
123
+ }
124
+ loadState() {
125
+ try {
126
+ return JSON.parse(fs_1.default.readFileSync(this.statePath, 'utf8'));
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ }
132
+ }
133
+ exports.VenvManager = VenvManager;
134
+ function venvPython(venvPath) {
135
+ return path_1.default.join(venvPath, process.platform === 'win32' ? 'Scripts' : 'bin', process.platform === 'win32' ? 'python.exe' : 'python');
136
+ }
137
+ function pathsEqual(left, right) {
138
+ const normalize = (value) => {
139
+ const resolved = path_1.default.resolve(value);
140
+ return process.platform === 'win32' ? resolved.toLowerCase() : resolved;
141
+ };
142
+ return normalize(left) === normalize(right);
143
+ }
144
+ class VenvCreationError extends Error {
145
+ constructor(message) {
146
+ super(message);
147
+ this.name = 'VenvCreationError';
148
+ }
149
+ }
150
+ exports.VenvCreationError = VenvCreationError;
151
+ class PackageInstallError extends Error {
152
+ packages;
153
+ constructor(packages, detail) {
154
+ super(`Failed to install packages [${packages.join(', ')}]: ${detail}`);
155
+ this.name = 'PackageInstallError';
156
+ this.packages = packages;
157
+ }
158
+ }
159
+ exports.PackageInstallError = PackageInstallError;
160
+ //# sourceMappingURL=venv-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"venv-manager.js","sourceRoot":"","sources":["../../src/env/venv-manager.ts"],"names":[],"mappings":"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"}