@dbx-tools/projen 0.9.51 → 0.9.58
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.
- package/README.md +56 -16
- package/index.ts +9 -6
- package/package.json +5 -6
- package/src/dbx-tools-config.ts +8 -0
- package/src/generated.ts +6 -0
- package/src/packages.ts +6 -0
- package/src/project-py.ts +89 -18
- package/src/project.ts +2 -1
- package/src/python-node-bindings-component.ts +71 -0
- package/src/python-node-bindings.ts +38 -14
- package/src/python-node-runtime.ts +56 -0
- package/src/vscode.ts +17 -1
- package/src/workspace-lock.ts +31 -13
- package/tasks/publish-python.ts +14 -6
- package/tasks/python-localize-imports.py +188 -0
- package/tasks/python-node-bindings-watch.ts +96 -0
- package/tasks/python-node-bindings.ts +42 -130
- package/tasks/python-node-runtime-watch.ts +40 -0
- package/tasks/python-sync.ts +85 -3
- package/tasks/release.ts +2 -1
- package/tasks/sync.ts +15 -3
- package/shims/python-node/bootstrap.ts +0 -129
- package/shims/python-node/child-process.ts +0 -96
- package/shims/python-node/crypto.ts +0 -60
- package/shims/python-node/fs-promises.ts +0 -179
- package/shims/python-node/fs.ts +0 -173
- package/shims/python-node/headers.ts +0 -75
- package/shims/python-node/host.ts +0 -341
- package/shims/python-node/os.ts +0 -20
- package/shims/python-node/process.ts +0 -13
- package/shims/python-node/readline.ts +0 -37
- package/shims/python-node/tsconfig.json +0 -24
- package/src/python-node-bundle.ts +0 -67
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
interface PythonBridge {
|
|
2
|
-
eval(source: string): unknown;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
interface PythonCompletedProcess {
|
|
6
|
-
returncode: number;
|
|
7
|
-
stdout: string | null;
|
|
8
|
-
stderr: string | null;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
interface PythonHttpResponse {
|
|
12
|
-
status_code: number;
|
|
13
|
-
headers: Record<string, string>;
|
|
14
|
-
content: Iterable<number>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface PythonFileHost {
|
|
18
|
-
appendBytes(path: string, content: number[]): Promise<void>;
|
|
19
|
-
chmod(path: string, mode: number): Promise<void>;
|
|
20
|
-
copy(source: string, destination: string): Promise<void>;
|
|
21
|
-
exists(path: string): boolean;
|
|
22
|
-
mkdir(path: string, recursive: boolean): Promise<boolean>;
|
|
23
|
-
mkdtemp(prefix: string): Promise<string>;
|
|
24
|
-
readBytes(path: string): Promise<number[]>;
|
|
25
|
-
readDirectory(path: string): Promise<{ name: string; directory: boolean; file: boolean }[]>;
|
|
26
|
-
readTextSync(path: string): string;
|
|
27
|
-
readDirectorySync(path: string): { name: string; directory: boolean; file: boolean }[];
|
|
28
|
-
readLinkSync(path: string): string;
|
|
29
|
-
realpath(path: string): Promise<string>;
|
|
30
|
-
realpathSync(path: string): string;
|
|
31
|
-
remove(path: string, recursive: boolean, force: boolean): Promise<void>;
|
|
32
|
-
rename(source: string, destination: string): Promise<void>;
|
|
33
|
-
stat(path: string): Promise<{
|
|
34
|
-
directory: boolean;
|
|
35
|
-
file: boolean;
|
|
36
|
-
mode: number;
|
|
37
|
-
mtimeMs: number;
|
|
38
|
-
size: number;
|
|
39
|
-
}>;
|
|
40
|
-
statSync(path: string): {
|
|
41
|
-
directory: boolean;
|
|
42
|
-
file: boolean;
|
|
43
|
-
mode: number;
|
|
44
|
-
mtimeMs: number;
|
|
45
|
-
size: number;
|
|
46
|
-
};
|
|
47
|
-
touch(path: string, atimeMs: number, mtimeMs: number): Promise<void>;
|
|
48
|
-
writeBytes(path: string, content: number[], mode?: number): Promise<void>;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface PythonPathHost {
|
|
52
|
-
basename(path: string): string;
|
|
53
|
-
dirname(path: string): string;
|
|
54
|
-
fileUrlToPath(url: string): string;
|
|
55
|
-
isAbsolute(path: string): boolean;
|
|
56
|
-
join(parts: string[]): string;
|
|
57
|
-
relative(from: string, to: string): string;
|
|
58
|
-
resolve(parts: string[]): string;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export interface PythonProcessResult {
|
|
62
|
-
exitCode: number;
|
|
63
|
-
stdout?: string;
|
|
64
|
-
stderr?: string;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/** A started subprocess: await {@link wait} for its result, or {@link kill} it. */
|
|
68
|
-
export interface PythonProcessHandle {
|
|
69
|
-
/** Terminate the child (SIGKILL). No-op once it has already exited. */
|
|
70
|
-
kill(): void;
|
|
71
|
-
/** Resolve with the child's result once it exits (runs off the main thread). */
|
|
72
|
-
wait(): Promise<PythonProcessResult>;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export interface PythonRuntimeHost {
|
|
76
|
-
crypto: {
|
|
77
|
-
digest(algorithm: string, content: number[], encoding?: "hex" | "base64"): string | number[];
|
|
78
|
-
hashes(): string[];
|
|
79
|
-
randomBytes(length: number): number[];
|
|
80
|
-
};
|
|
81
|
-
file: PythonFileHost;
|
|
82
|
-
os: {
|
|
83
|
-
homedir(): string;
|
|
84
|
-
tmpdir(): string;
|
|
85
|
-
};
|
|
86
|
-
path: PythonPathHost;
|
|
87
|
-
http: {
|
|
88
|
-
fetch(
|
|
89
|
-
url: string,
|
|
90
|
-
method?: string,
|
|
91
|
-
headers?: Record<string, string>,
|
|
92
|
-
body?: string,
|
|
93
|
-
timeoutMs?: number,
|
|
94
|
-
): Promise<{ status: number; headers: Record<string, string>; body: number[] }>;
|
|
95
|
-
};
|
|
96
|
-
process: {
|
|
97
|
-
start(
|
|
98
|
-
command: string,
|
|
99
|
-
args: string[],
|
|
100
|
-
environment: Record<string, string> | undefined,
|
|
101
|
-
input: string | undefined,
|
|
102
|
-
): PythonProcessHandle;
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
type PythonFunction = (...args: any[]) => any;
|
|
107
|
-
|
|
108
|
-
const python = (globalThis as typeof globalThis & { python?: PythonBridge }).python;
|
|
109
|
-
if (!python) throw new Error("PythonMonkey globalThis.python is unavailable");
|
|
110
|
-
|
|
111
|
-
function evaluate<T extends PythonFunction>(source: string): T {
|
|
112
|
-
return python!.eval(source) as T;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const toThread = evaluate<PythonFunction>("__import__('asyncio').to_thread");
|
|
116
|
-
const osPath = {
|
|
117
|
-
basename: evaluate<PythonFunction>("__import__('os').path.basename"),
|
|
118
|
-
dirname: evaluate<PythonFunction>("__import__('os').path.dirname"),
|
|
119
|
-
exists: evaluate<PythonFunction>("__import__('os').path.exists"),
|
|
120
|
-
isAbsolute: evaluate<PythonFunction>("__import__('os').path.isabs"),
|
|
121
|
-
join: evaluate<PythonFunction>("lambda parts: __import__('os').path.join(*list(parts))"),
|
|
122
|
-
realpath: evaluate<PythonFunction>("__import__('os').path.realpath"),
|
|
123
|
-
relative: evaluate<PythonFunction>("__import__('os').path.relpath"),
|
|
124
|
-
resolve: evaluate<PythonFunction>(
|
|
125
|
-
"lambda parts: __import__('os').path.abspath(__import__('os').path.join(*list(parts))) if list(parts) else __import__('os').getcwd()",
|
|
126
|
-
),
|
|
127
|
-
};
|
|
128
|
-
const readBytes = evaluate<PythonFunction>("lambda path: list(open(path, 'rb').read())");
|
|
129
|
-
const readText = evaluate<PythonFunction>("lambda path: open(path, encoding='utf-8').read()");
|
|
130
|
-
const writeBytes = evaluate<PythonFunction>(
|
|
131
|
-
"lambda path, content: open(path, 'wb').write(bytes(int(value) for value in content))",
|
|
132
|
-
);
|
|
133
|
-
const appendBytes = evaluate<PythonFunction>(
|
|
134
|
-
"lambda path, content: open(path, 'ab').write(bytes(int(value) for value in content))",
|
|
135
|
-
);
|
|
136
|
-
const mkdir = evaluate<PythonFunction>(
|
|
137
|
-
"lambda path, recursive: __import__('os').makedirs(path, exist_ok=recursive) if recursive else __import__('os').mkdir(path)",
|
|
138
|
-
);
|
|
139
|
-
const listDirectory = evaluate<PythonFunction>(
|
|
140
|
-
"lambda path: [{'name': entry.name, 'directory': entry.is_dir(), 'file': entry.is_file()} for entry in __import__('pathlib').Path(path).iterdir()]",
|
|
141
|
-
);
|
|
142
|
-
const readLink = evaluate<PythonFunction>("__import__('os').readlink");
|
|
143
|
-
const statPath = evaluate<PythonFunction>(
|
|
144
|
-
"lambda path: {'directory': __import__('os').path.isdir(path), 'file': __import__('os').path.isfile(path), 'mode': __import__('os').stat(path).st_mode, 'mtimeMs': __import__('os').stat(path).st_mtime * 1000, 'size': __import__('os').stat(path).st_size}",
|
|
145
|
-
);
|
|
146
|
-
const popen = evaluate<PythonFunction>(
|
|
147
|
-
"lambda command, args, environment, input_text: __import__('subprocess').Popen([command, *list(args)], env=dict(environment) if environment is not None else None, stdin=(__import__('subprocess').PIPE if input_text is not None else None), stdout=__import__('subprocess').PIPE, stderr=__import__('subprocess').PIPE, text=True)",
|
|
148
|
-
);
|
|
149
|
-
const communicate = evaluate<PythonFunction>(
|
|
150
|
-
"lambda proc, input_text: (lambda out: {'returncode': proc.returncode, 'stdout': out[0], 'stderr': out[1]})(proc.communicate(input=input_text))",
|
|
151
|
-
);
|
|
152
|
-
const killProcess = evaluate<PythonFunction>("lambda proc: proc.kill()");
|
|
153
|
-
const requestHttp = evaluate<PythonFunction>(
|
|
154
|
-
"lambda url, method, headers, body, timeout: __import__('httpx').request(method or 'GET', url, headers=dict(headers) if headers is not None else None, content=body, timeout=(timeout / 1000) if timeout is not None else 30, follow_redirects=True)",
|
|
155
|
-
);
|
|
156
|
-
const chmod = evaluate<PythonFunction>(
|
|
157
|
-
"lambda path, mode: __import__('os').chmod(path, int(mode))",
|
|
158
|
-
);
|
|
159
|
-
const isDir = evaluate<PythonFunction>("__import__('os').path.isdir");
|
|
160
|
-
const rmtree = evaluate<PythonFunction>("__import__('shutil').rmtree");
|
|
161
|
-
const rmdir = evaluate<PythonFunction>("__import__('os').rmdir");
|
|
162
|
-
const unlink = evaluate<PythonFunction>("__import__('os').unlink");
|
|
163
|
-
|
|
164
|
-
const host: PythonRuntimeHost = {
|
|
165
|
-
crypto: {
|
|
166
|
-
digest: evaluate<PythonFunction>(
|
|
167
|
-
"lambda algorithm, content, encoding: (lambda value: value.hexdigest() if encoding == 'hex' else __import__('base64').b64encode(value.digest()).decode('ascii') if encoding == 'base64' else list(value.digest()))(__import__('hashlib').new(algorithm, bytes(int(item) for item in content)))",
|
|
168
|
-
),
|
|
169
|
-
hashes: evaluate<PythonFunction>("lambda: sorted(__import__('hashlib').algorithms_available)"),
|
|
170
|
-
randomBytes: evaluate<PythonFunction>(
|
|
171
|
-
"lambda length: list(__import__('os').urandom(int(length)))",
|
|
172
|
-
),
|
|
173
|
-
},
|
|
174
|
-
file: {
|
|
175
|
-
async appendBytes(path, content) {
|
|
176
|
-
await toThread(appendBytes, path, content);
|
|
177
|
-
},
|
|
178
|
-
async chmod(path, mode) {
|
|
179
|
-
await toThread(chmod, path, mode);
|
|
180
|
-
},
|
|
181
|
-
async copy(source, destination) {
|
|
182
|
-
await toThread(
|
|
183
|
-
evaluate<PythonFunction>("__import__('shutil').copyfile"),
|
|
184
|
-
source,
|
|
185
|
-
destination,
|
|
186
|
-
);
|
|
187
|
-
},
|
|
188
|
-
exists: (path) => Boolean(osPath.exists(path)),
|
|
189
|
-
async mkdir(path, recursive) {
|
|
190
|
-
if (await toThread(osPath.exists, path)) return false;
|
|
191
|
-
await toThread(mkdir, path, recursive);
|
|
192
|
-
return true;
|
|
193
|
-
},
|
|
194
|
-
async mkdtemp(prefix) {
|
|
195
|
-
return toThread(
|
|
196
|
-
evaluate<PythonFunction>("__import__('tempfile').mkdtemp"),
|
|
197
|
-
undefined,
|
|
198
|
-
prefix,
|
|
199
|
-
);
|
|
200
|
-
},
|
|
201
|
-
async readBytes(path) {
|
|
202
|
-
return toThread(readBytes, path);
|
|
203
|
-
},
|
|
204
|
-
async readDirectory(path) {
|
|
205
|
-
return toThread(listDirectory, path);
|
|
206
|
-
},
|
|
207
|
-
readDirectorySync: (path) => listDirectory(path),
|
|
208
|
-
readLinkSync: (path) => String(readLink(path)),
|
|
209
|
-
readTextSync: (path) => String(readText(path)),
|
|
210
|
-
async realpath(path) {
|
|
211
|
-
return String(await toThread(osPath.realpath, path));
|
|
212
|
-
},
|
|
213
|
-
realpathSync: (path) => String(osPath.realpath(path)),
|
|
214
|
-
async remove(path, recursive, force) {
|
|
215
|
-
if (!(await toThread(osPath.exists, path))) {
|
|
216
|
-
if (!force) throw Object.assign(new Error(`ENOENT: ${path}`), { code: "ENOENT" });
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
const isDirectory = await toThread(isDir, path);
|
|
220
|
-
const operation = isDirectory ? (recursive ? rmtree : rmdir) : unlink;
|
|
221
|
-
await toThread(operation, path);
|
|
222
|
-
},
|
|
223
|
-
async rename(source, destination) {
|
|
224
|
-
await toThread(evaluate<PythonFunction>("__import__('os').replace"), source, destination);
|
|
225
|
-
},
|
|
226
|
-
async stat(path) {
|
|
227
|
-
return toThread(statPath, path);
|
|
228
|
-
},
|
|
229
|
-
statSync: (path) => statPath(path),
|
|
230
|
-
async touch(path, atimeMs, mtimeMs) {
|
|
231
|
-
await toThread(
|
|
232
|
-
evaluate<PythonFunction>(
|
|
233
|
-
"lambda path, atime, mtime: __import__('os').utime(path, (atime / 1000, mtime / 1000))",
|
|
234
|
-
),
|
|
235
|
-
path,
|
|
236
|
-
atimeMs,
|
|
237
|
-
mtimeMs,
|
|
238
|
-
);
|
|
239
|
-
},
|
|
240
|
-
async writeBytes(path, content, mode) {
|
|
241
|
-
await toThread(writeBytes, path, content);
|
|
242
|
-
if (mode !== undefined) await toThread(chmod, path, mode);
|
|
243
|
-
},
|
|
244
|
-
},
|
|
245
|
-
http: {
|
|
246
|
-
async fetch(url, method, headers, body, timeoutMs) {
|
|
247
|
-
const response = (await toThread(
|
|
248
|
-
requestHttp,
|
|
249
|
-
url,
|
|
250
|
-
method,
|
|
251
|
-
headers,
|
|
252
|
-
body,
|
|
253
|
-
timeoutMs,
|
|
254
|
-
)) as PythonHttpResponse;
|
|
255
|
-
return {
|
|
256
|
-
status: response.status_code,
|
|
257
|
-
headers: Object.fromEntries(Object.entries(response.headers)),
|
|
258
|
-
body: Array.from(response.content),
|
|
259
|
-
};
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
os: {
|
|
263
|
-
homedir: evaluate<PythonFunction>("lambda: __import__('pathlib').Path.home().as_posix()"),
|
|
264
|
-
tmpdir: evaluate<PythonFunction>("__import__('tempfile').gettempdir"),
|
|
265
|
-
},
|
|
266
|
-
path: {
|
|
267
|
-
basename: (path) => String(osPath.basename(path)),
|
|
268
|
-
dirname: (path) => String(osPath.dirname(path)),
|
|
269
|
-
fileUrlToPath: evaluate<PythonFunction>(
|
|
270
|
-
"lambda url: __import__('urllib.parse', fromlist=['urlparse']).unquote(__import__('urllib.parse', fromlist=['urlparse']).urlparse(url).path)",
|
|
271
|
-
),
|
|
272
|
-
isAbsolute: (path) => Boolean(osPath.isAbsolute(path)),
|
|
273
|
-
join: (parts) => String(osPath.join(parts)),
|
|
274
|
-
relative: (from, to) => String(osPath.relative(to, from)),
|
|
275
|
-
resolve: (parts) => String(osPath.resolve(parts)),
|
|
276
|
-
},
|
|
277
|
-
process: {
|
|
278
|
-
start(command, args, environment, input) {
|
|
279
|
-
// Popen (not subprocess.run) so the child is killable: an aborted caller
|
|
280
|
-
// can terminate it instead of leaking a background process. There is no
|
|
281
|
-
// imposed timeout - the child runs to completion (an interactive login may
|
|
282
|
-
// legitimately take minutes); the caller owns cancellation.
|
|
283
|
-
const proc = popen(command, args, environment, input);
|
|
284
|
-
let killed = false;
|
|
285
|
-
return {
|
|
286
|
-
kill() {
|
|
287
|
-
if (killed) return;
|
|
288
|
-
killed = true;
|
|
289
|
-
try {
|
|
290
|
-
killProcess(proc);
|
|
291
|
-
} catch {
|
|
292
|
-
// The child already exited; there is nothing to signal.
|
|
293
|
-
}
|
|
294
|
-
},
|
|
295
|
-
async wait() {
|
|
296
|
-
// communicate() blocks until exit, so run it off the main thread.
|
|
297
|
-
const result = (await toThread(communicate, proc, input)) as PythonCompletedProcess;
|
|
298
|
-
return {
|
|
299
|
-
exitCode: result.returncode,
|
|
300
|
-
...(result.stdout?.trim() ? { stdout: result.stdout.trim() } : {}),
|
|
301
|
-
...(result.stderr?.trim() ? { stderr: result.stderr.trim() } : {}),
|
|
302
|
-
};
|
|
303
|
-
},
|
|
304
|
-
};
|
|
305
|
-
},
|
|
306
|
-
},
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
export function installPythonGlobals(): void {
|
|
310
|
-
const globals = globalThis as typeof globalThis & {
|
|
311
|
-
global?: typeof globalThis;
|
|
312
|
-
self?: typeof globalThis;
|
|
313
|
-
window?: typeof globalThis;
|
|
314
|
-
process?: Record<string, unknown>;
|
|
315
|
-
};
|
|
316
|
-
globals.global = globalThis;
|
|
317
|
-
globals.self = globalThis;
|
|
318
|
-
globals.window = globalThis;
|
|
319
|
-
globals.process ??= {
|
|
320
|
-
arch: String(evaluate<PythonFunction>("__import__('platform').machine")())
|
|
321
|
-
.replace("aarch64", "arm64")
|
|
322
|
-
.replace("x86_64", "x64"),
|
|
323
|
-
argv: [],
|
|
324
|
-
browser: true,
|
|
325
|
-
cwd: evaluate<PythonFunction>("__import__('os').getcwd"),
|
|
326
|
-
env: evaluate<PythonFunction>("lambda: dict(__import__('os').environ)")(),
|
|
327
|
-
nextTick: (callback: (...args: unknown[]) => void, ...args: unknown[]) =>
|
|
328
|
-
Promise.resolve().then(() => callback(...args)),
|
|
329
|
-
platform: { Darwin: "darwin", Linux: "linux", Windows: "win32" }[
|
|
330
|
-
String(evaluate<PythonFunction>("__import__('platform').system")())
|
|
331
|
-
],
|
|
332
|
-
version: "v22.0.0",
|
|
333
|
-
versions: {},
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
installPythonGlobals();
|
|
338
|
-
|
|
339
|
-
export function pythonHost(): PythonRuntimeHost {
|
|
340
|
-
return host;
|
|
341
|
-
}
|
package/shims/python-node/os.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { pythonHost } from "./host.ts";
|
|
2
|
-
|
|
3
|
-
export const constants = {
|
|
4
|
-
errno: {
|
|
5
|
-
EEXIST: 17,
|
|
6
|
-
ENOTDIR: 20,
|
|
7
|
-
EISDIR: 21,
|
|
8
|
-
EINVAL: 22,
|
|
9
|
-
},
|
|
10
|
-
} as const;
|
|
11
|
-
|
|
12
|
-
export function homedir(): string {
|
|
13
|
-
return pythonHost().os.homedir();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function tmpdir(): string {
|
|
17
|
-
return pythonHost().os.tmpdir();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default { constants, homedir, tmpdir };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { installPythonGlobals } from "./host.ts";
|
|
2
|
-
|
|
3
|
-
installPythonGlobals();
|
|
4
|
-
|
|
5
|
-
export default process;
|
|
6
|
-
export const arch = process.arch;
|
|
7
|
-
export const argv = process.argv;
|
|
8
|
-
export const cwd = process.cwd;
|
|
9
|
-
export const env = process.env;
|
|
10
|
-
export const nextTick = process.nextTick;
|
|
11
|
-
export const platform = process.platform;
|
|
12
|
-
export const version = process.version;
|
|
13
|
-
export const versions = process.versions;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Async line reader used by subprocess output capture in PythonMonkey bundles.
|
|
3
|
-
*
|
|
4
|
-
* @module
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
interface ReadLineOptions {
|
|
8
|
-
readonly input: AsyncIterable<unknown>;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
class PythonReadLine implements AsyncIterable<string> {
|
|
12
|
-
private closed = false;
|
|
13
|
-
|
|
14
|
-
constructor(private readonly input: AsyncIterable<unknown>) {}
|
|
15
|
-
|
|
16
|
-
async *[Symbol.asyncIterator](): AsyncIterator<string> {
|
|
17
|
-
let buffered = "";
|
|
18
|
-
for await (const chunk of this.input) {
|
|
19
|
-
if (this.closed) break;
|
|
20
|
-
buffered += String(chunk);
|
|
21
|
-
const lines = buffered.split(/\r?\n/);
|
|
22
|
-
buffered = lines.pop() ?? "";
|
|
23
|
-
for (const line of lines) yield line;
|
|
24
|
-
}
|
|
25
|
-
if (!this.closed && buffered) yield buffered.replace(/\r$/, "");
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
close(): void {
|
|
29
|
-
this.closed = true;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function createInterface(options: ReadLineOptions): PythonReadLine {
|
|
34
|
-
return new PythonReadLine(options.input);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export default { createInterface };
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// ~~ Generated by projen. To modify, edit .projenrc.js and run "bunx projen".
|
|
2
|
-
{
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"target": "ES2022",
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"moduleResolution": "bundler",
|
|
7
|
-
"lib": [
|
|
8
|
-
"ES2022",
|
|
9
|
-
"DOM"
|
|
10
|
-
],
|
|
11
|
-
"types": [
|
|
12
|
-
"node"
|
|
13
|
-
],
|
|
14
|
-
"noEmit": true,
|
|
15
|
-
"skipLibCheck": true,
|
|
16
|
-
"strict": false
|
|
17
|
-
},
|
|
18
|
-
"include": [
|
|
19
|
-
"*.ts"
|
|
20
|
-
],
|
|
21
|
-
"exclude": [
|
|
22
|
-
"node_modules"
|
|
23
|
-
]
|
|
24
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Projen task wiring for pyproject-driven PythonMonkey runtime generation.
|
|
3
|
-
*
|
|
4
|
-
* Type extraction and bundle emission remain in the executable generator; this
|
|
5
|
-
* component owns only typed configuration and generate/check task registration.
|
|
6
|
-
*/
|
|
7
|
-
import { Component, type Project, type Task } from "projen";
|
|
8
|
-
import { taskCommand } from "./project-js.ts";
|
|
9
|
-
|
|
10
|
-
/** One function replaced only in a generated PythonMonkey bundle. */
|
|
11
|
-
export interface PythonNodeFunctionOverride {
|
|
12
|
-
/** Module specifier imported by the ordinary Node source. */
|
|
13
|
-
readonly module: string;
|
|
14
|
-
/** Named export to replace. */
|
|
15
|
-
readonly export: string;
|
|
16
|
-
/** Repository-relative TypeScript file containing the replacement. */
|
|
17
|
-
readonly handler: string;
|
|
18
|
-
/** Named export in {@link handler}. Defaults to {@link export}. */
|
|
19
|
-
readonly handlerExport?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/** Node package embedded into one Python distribution through PythonMonkey. */
|
|
23
|
-
export interface PythonNodeBindingsOptions {
|
|
24
|
-
/** Public Node package specifier, such as `@dbx-tools/auth`. */
|
|
25
|
-
readonly package: string;
|
|
26
|
-
/** Optional portable package subpath to bind. Defaults to {@link package}. */
|
|
27
|
-
readonly entrypoint?: string;
|
|
28
|
-
/** Automatically generated root namespace modules to bind independently. */
|
|
29
|
-
readonly modules?: readonly string[];
|
|
30
|
-
/** Functions replaced only while generating the Python runtime. */
|
|
31
|
-
readonly functionOverrides?: readonly PythonNodeFunctionOverride[];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** Options for pyproject-driven PythonMonkey generation tasks. */
|
|
35
|
-
export interface PythonNodeBundleOptions {
|
|
36
|
-
/** Stable task-name prefix, such as `auth`. */
|
|
37
|
-
readonly name: string;
|
|
38
|
-
/** Repository-relative Python project containing `pyproject.toml`. */
|
|
39
|
-
readonly projectDirectory: string;
|
|
40
|
-
/** Add the freshness check to the project's test task. Defaults to true. */
|
|
41
|
-
readonly test?: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** Owns paired generation and freshness-check tasks for one Python package. */
|
|
45
|
-
export class PythonNodeBundle extends Component {
|
|
46
|
-
readonly buildTask: Task;
|
|
47
|
-
readonly checkTask: Task;
|
|
48
|
-
readonly watchTask: Task;
|
|
49
|
-
|
|
50
|
-
constructor(project: Project, options: PythonNodeBundleOptions) {
|
|
51
|
-
super(project);
|
|
52
|
-
const command = taskCommand("python-node-bindings.ts", "--project", options.projectDirectory);
|
|
53
|
-
this.buildTask = project.addTask(`${options.name}:python-runtime`, {
|
|
54
|
-
description: `Generate Node bindings for Python package ${options.name}`,
|
|
55
|
-
execArgs: command,
|
|
56
|
-
});
|
|
57
|
-
this.checkTask = project.addTask(`${options.name}:python-runtime:check`, {
|
|
58
|
-
description: `Verify generated Node bindings for Python package ${options.name}`,
|
|
59
|
-
execArgs: [...command, "--check"],
|
|
60
|
-
});
|
|
61
|
-
this.watchTask = project.addTask(`${options.name}:python-runtime:watch`, {
|
|
62
|
-
description: `Watch and regenerate Node bindings for Python package ${options.name}`,
|
|
63
|
-
execArgs: taskCommand("python-node-bindings-watch.ts", "--project", options.projectDirectory),
|
|
64
|
-
});
|
|
65
|
-
if (options.test ?? true) project.testTask.spawn(this.checkTask);
|
|
66
|
-
}
|
|
67
|
-
}
|