-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmod.ts
172 lines (145 loc) · 4.2 KB
/
mod.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/**
* NOTE: you should run
* ```
* uv init
* uv sync
* source .venv/bin/activate
* ```
* before using this module.
*/
import { $ } from "jsr:@david/dax@^0.42.0";
import { dirname, join } from "jsr:@std/path@1";
let py: typeof import("jsr:@denosaurs/[email protected]") | undefined;
/**
* Gets a python interpreter interface with the python path
* set up. This allows you to use uv, venv, etc.
*
* Most of the time, you will use `import` on this object,
* and also make use of some common built-ins attached to
* this object, such as `str`, `int`, `tuple`, etc.
*
* NOTE: You should source a python virtual environment before using
* this module.
*
* If you are using uv, you can run:
* ```
* uv init
* uv sync
* source .venv/bin/activate
* ```
*
* If you are using a different venv path, run:
* ```
* source {MY_PYTHON_PROJECT_PATH}/.venv/bin/activate
* ```
*
* Learn more about uv at https://docs.astral.sh/uv/
*/
export const getPython = async (): Promise<
typeof import("jsr:@denosaurs/[email protected]")
> => {
if (py) {
return py;
}
const venvDir = Deno.env.get("VIRTUAL_ENV");
if (!venvDir) {
if (Deno.env.get("ORGSOFT_PY_NO_WARNING") !== "true") {
console.warn(
`%c
⚠️ Warning: \`VIRTUAL_ENV\` is not set. In order to use @orgsoft/py as recommended,
you should first activate a virtual environment in your active shell with:
%c\`\`\`sh
source .venv/bin/activate
\`\`\`%c
If you are using a different venv path, run:
%c\`\`\`sh
source {MY_PYTHON_PROJECT_PATH}/.venv/bin/activate
\`\`\`%c
We recommend using uv to create your virtual environment.
Get uv from: https://docs.astral.sh/uv/
Then, run:
%c\`\`\`sh
uv init
uv sync
source .venv/bin/activate
\`\`\`%c
to create and activate your virtual environment.
You can disable this warning by setting the environment variable:
%c\`\`\`sh
ORGSOFT_PY_NO_WARNING=true
\`\`\`
`,
"color:yellow",
"color:purple",
"color:yellow",
"color:purple",
"color:yellow",
"color:purple",
"color:yellow",
"color:purple",
);
}
return await import("jsr:@denosaurs/[email protected]");
}
// We need to bootstrap the python path with an existing python command
const pythonPath =
await $`python -c 'import sysconfig, os; print(os.path.join(sysconfig.get_config_var("LIBDIR"), sysconfig.get_config_var("INSTSONAME")))'`
.text();
const home = dirname(dirname(pythonPath));
// get first subdir of sitePackagesDir
const sitePackagesDir = join(venvDir, "lib");
const iter = await Deno.readDir(sitePackagesDir);
let firstSubdir: string | undefined;
for await (const entry of iter) {
firstSubdir = entry.name;
break;
}
if (!firstSubdir && Deno.env.get("ORGSOFT_PY_NO_WARNING") !== "true") {
console.warn(`%sNo packages found in ${sitePackagesDir}`, "color:yellow");
}
const sitePackagesPath = firstSubdir
? join(sitePackagesDir, firstSubdir, "site-packages")
: undefined;
Deno.env.set("DENO_PYTHON_PATH", pythonPath);
Deno.env.set("PYTHONHOME", home);
Deno.env.set("PYTHONPATH", sitePackagesPath ?? "");
py = await import("jsr:@denosaurs/[email protected]");
// Append current dir and sitePackagesPath to path
py.python.run(`import sys
import os
sys.path.append(os.getcwd())
${sitePackagesPath ? `sys.path.append("${sitePackagesPath}")` : ""}
`);
return py;
};
if (import.meta.main) {
const { python } = await getPython();
if (Deno.env.get("ORGSOFT_PY_NO_WARNING") !== "true") {
console.warn(
`"%c\n⚠️ Warning: No arguments provided, running main.py (if it exists)
Usage:
%c
deno run --allow-ffi --allow-env --allow-read --allow-run jsr:@orgsoft/py/mod.ts <python_module>
%c
You can use orgsoft/py to run python code in code with:
%c
import { getPython } from "jsr:@orgsoft/py";
const { python } = await getPython();
const module = await python.import("my_module");
const result = await module.main();
console.log(result);
%c
Disable this warning by setting the environment variable:
%c
ORGSOFT_PY_NO_WARNING=true
`,
"color:yellow",
"color:purple",
"color:yellow",
"color:purple",
"color:yellow",
"color:purple",
);
}
python.run("import runpy\nrunpy.run_module('main', run_name='__main__')");
}