@vercel/python 6.16.1 → 6.17.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.
- package/dist/index.js +91 -25
- package/package.json +5 -5
- package/vc_init_dev.py +17 -5
package/dist/index.js
CHANGED
|
@@ -2871,8 +2871,8 @@ var import_fs6 = __toESM(require("fs"));
|
|
|
2871
2871
|
var import_util2 = require("util");
|
|
2872
2872
|
var import_path8 = require("path");
|
|
2873
2873
|
|
|
2874
|
-
// src/
|
|
2875
|
-
var VERCEL_RUNTIME_VERSION = "0.5.
|
|
2874
|
+
// src/package-versions.ts
|
|
2875
|
+
var VERCEL_RUNTIME_VERSION = "0.5.2";
|
|
2876
2876
|
|
|
2877
2877
|
// src/index.ts
|
|
2878
2878
|
var import_build_utils9 = require("@vercel/build-utils");
|
|
@@ -4264,11 +4264,16 @@ var PYTHON_ENTRYPOINT_FILENAMES = [
|
|
|
4264
4264
|
"asgi"
|
|
4265
4265
|
];
|
|
4266
4266
|
var PYTHON_ENTRYPOINT_DIRS = ["", "src", "app", "api"];
|
|
4267
|
-
var PYTHON_CANDIDATE_ENTRYPOINTS =
|
|
4268
|
-
|
|
4269
|
-
(dir) => import_path6.posix.join(dir, `${filename}.py`)
|
|
4270
|
-
)
|
|
4267
|
+
var PYTHON_CANDIDATE_ENTRYPOINTS = getCandidateEntrypointsInDirs(
|
|
4268
|
+
PYTHON_ENTRYPOINT_DIRS
|
|
4271
4269
|
);
|
|
4270
|
+
function getCandidateEntrypointsInDirs(dirs) {
|
|
4271
|
+
return dirs.flatMap(
|
|
4272
|
+
(dir) => PYTHON_ENTRYPOINT_FILENAMES.map(
|
|
4273
|
+
(filename) => import_path6.posix.join(dir, `${filename}.py`)
|
|
4274
|
+
)
|
|
4275
|
+
);
|
|
4276
|
+
}
|
|
4272
4277
|
async function getPyprojectEntrypoint(workPath) {
|
|
4273
4278
|
const pyprojectData = await (0, import_build_utils7.readConfigFile)((0, import_path6.join)(workPath, "pyproject.toml"));
|
|
4274
4279
|
if (!pyprojectData)
|
|
@@ -4295,6 +4300,18 @@ async function getPyprojectEntrypoint(workPath) {
|
|
|
4295
4300
|
return null;
|
|
4296
4301
|
}
|
|
4297
4302
|
}
|
|
4303
|
+
async function findValidEntrypoint(fsFiles, candidates) {
|
|
4304
|
+
for (const candidate of candidates) {
|
|
4305
|
+
if (fsFiles[candidate]) {
|
|
4306
|
+
const isValid = await (0, import_build_utils6.isPythonEntrypoint)(fsFiles[candidate]);
|
|
4307
|
+
if (isValid) {
|
|
4308
|
+
(0, import_build_utils6.debug)(`Detected Python entrypoint: ${candidate}`);
|
|
4309
|
+
return candidate;
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
return null;
|
|
4314
|
+
}
|
|
4298
4315
|
async function detectGenericPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
4299
4316
|
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
4300
4317
|
try {
|
|
@@ -4309,24 +4326,54 @@ async function detectGenericPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
|
4309
4326
|
const candidates = PYTHON_CANDIDATE_ENTRYPOINTS.filter(
|
|
4310
4327
|
(c) => !!fsFiles[c]
|
|
4311
4328
|
);
|
|
4312
|
-
|
|
4313
|
-
|
|
4329
|
+
return findValidEntrypoint(fsFiles, candidates);
|
|
4330
|
+
} catch {
|
|
4331
|
+
(0, import_build_utils6.debug)("Failed to discover Python entrypoint");
|
|
4332
|
+
return null;
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
async function detectDjangoPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
4336
|
+
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
4337
|
+
try {
|
|
4338
|
+
const fsFiles = await (0, import_build_utils6.glob)("**", workPath);
|
|
4339
|
+
if (fsFiles[entry]) {
|
|
4340
|
+
const isValid = await (0, import_build_utils6.isPythonEntrypoint)(fsFiles[entry]);
|
|
4314
4341
|
if (isValid) {
|
|
4315
|
-
(0, import_build_utils6.debug)(`
|
|
4316
|
-
return
|
|
4342
|
+
(0, import_build_utils6.debug)(`Using configured Python entrypoint: ${entry}`);
|
|
4343
|
+
return entry;
|
|
4317
4344
|
}
|
|
4318
4345
|
}
|
|
4319
|
-
|
|
4346
|
+
const rootGlobs = await (0, import_build_utils6.glob)("*", {
|
|
4347
|
+
cwd: workPath,
|
|
4348
|
+
includeDirectories: true
|
|
4349
|
+
});
|
|
4350
|
+
const rootDirs = [
|
|
4351
|
+
"",
|
|
4352
|
+
...Object.keys(rootGlobs).filter(
|
|
4353
|
+
(name) => !name.startsWith(".") && rootGlobs[name].mode != null && (0, import_build_utils6.isDirectory)(rootGlobs[name].mode)
|
|
4354
|
+
)
|
|
4355
|
+
];
|
|
4356
|
+
for (const rootDir of rootDirs) {
|
|
4357
|
+
const currPath = (0, import_path6.join)(workPath, rootDir);
|
|
4358
|
+
const wsgiEntry = await (0, import_build_utils6.getDjangoEntrypoint)(currPath);
|
|
4359
|
+
if (wsgiEntry) {
|
|
4360
|
+
const fullWsgiEntry = import_path6.posix.join(rootDir, wsgiEntry);
|
|
4361
|
+
if (fsFiles[fullWsgiEntry]) {
|
|
4362
|
+
(0, import_build_utils6.debug)(`Using Django WSGI entrypoint: ${fullWsgiEntry}`);
|
|
4363
|
+
return fullWsgiEntry;
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
const baseCandidates = getCandidateEntrypointsInDirs(rootDirs);
|
|
4368
|
+
const candidates = baseCandidates.filter((c) => !!fsFiles[c]);
|
|
4369
|
+
return findValidEntrypoint(fsFiles, candidates);
|
|
4320
4370
|
} catch {
|
|
4321
|
-
(0, import_build_utils6.debug)("Failed to discover Python entrypoint");
|
|
4371
|
+
(0, import_build_utils6.debug)("Failed to discover Django Python entrypoint");
|
|
4322
4372
|
return null;
|
|
4323
4373
|
}
|
|
4324
4374
|
}
|
|
4325
|
-
async function detectPythonEntrypoint(
|
|
4326
|
-
const entrypoint = await detectGenericPythonEntrypoint(
|
|
4327
|
-
workPath,
|
|
4328
|
-
configuredEntrypoint
|
|
4329
|
-
);
|
|
4375
|
+
async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint) {
|
|
4376
|
+
const entrypoint = framework === "django" ? await detectDjangoPythonEntrypoint(workPath, configuredEntrypoint) : await detectGenericPythonEntrypoint(workPath, configuredEntrypoint);
|
|
4330
4377
|
if (entrypoint)
|
|
4331
4378
|
return entrypoint;
|
|
4332
4379
|
return await getPyprojectEntrypoint(workPath);
|
|
@@ -4579,17 +4626,25 @@ function installGlobalCleanupHandlers() {
|
|
|
4579
4626
|
killAll();
|
|
4580
4627
|
});
|
|
4581
4628
|
}
|
|
4582
|
-
function createDevShim(workPath, modulePath) {
|
|
4629
|
+
function createDevShim(workPath, entry, modulePath) {
|
|
4583
4630
|
try {
|
|
4584
4631
|
const vercelPythonDir = (0, import_path7.join)(workPath, ".vercel", "python");
|
|
4585
4632
|
(0, import_fs5.mkdirSync)(vercelPythonDir, { recursive: true });
|
|
4633
|
+
let qualifiedModule = modulePath;
|
|
4634
|
+
let extraPythonPath;
|
|
4635
|
+
if ((0, import_fs5.existsSync)((0, import_path7.join)(workPath, "__init__.py"))) {
|
|
4636
|
+
const pkgName = (0, import_path7.basename)(workPath);
|
|
4637
|
+
qualifiedModule = `${pkgName}.${modulePath}`;
|
|
4638
|
+
extraPythonPath = (0, import_path7.dirname)(workPath);
|
|
4639
|
+
}
|
|
4640
|
+
const entryAbs = (0, import_path7.join)(workPath, entry);
|
|
4586
4641
|
const shimPath = (0, import_path7.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
|
|
4587
4642
|
const templatePath = (0, import_path7.join)(__dirname, "..", `${DEV_SHIM_MODULE}.py`);
|
|
4588
4643
|
const template = (0, import_fs5.readFileSync)(templatePath, "utf8");
|
|
4589
|
-
const shimSource = template.replace(/
|
|
4644
|
+
const shimSource = template.replace(/__VC_DEV_MODULE_NAME__/g, qualifiedModule).replace(/__VC_DEV_ENTRY_ABS__/g, entryAbs);
|
|
4590
4645
|
(0, import_fs5.writeFileSync)(shimPath, shimSource, "utf8");
|
|
4591
4646
|
(0, import_build_utils8.debug)(`Prepared Python dev shim at ${shimPath}`);
|
|
4592
|
-
return DEV_SHIM_MODULE;
|
|
4647
|
+
return { module: DEV_SHIM_MODULE, extraPythonPath };
|
|
4593
4648
|
} catch (err) {
|
|
4594
4649
|
(0, import_build_utils8.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
|
|
4595
4650
|
return null;
|
|
@@ -4753,22 +4808,33 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
4753
4808
|
}
|
|
4754
4809
|
const port = typeof meta.port === "number" ? meta.port : await (0, import_get_port.default)();
|
|
4755
4810
|
env.PORT = `${port}`;
|
|
4756
|
-
const
|
|
4757
|
-
if (
|
|
4811
|
+
const devShim = createDevShim(workPath, entry, modulePath);
|
|
4812
|
+
if (devShim) {
|
|
4758
4813
|
const vercelPythonDir = (0, import_path7.join)(workPath, ".vercel", "python");
|
|
4814
|
+
const pathParts = [vercelPythonDir];
|
|
4815
|
+
if (devShim.extraPythonPath) {
|
|
4816
|
+
pathParts.push(devShim.extraPythonPath);
|
|
4817
|
+
}
|
|
4759
4818
|
const existingPythonPath = env.PYTHONPATH || "";
|
|
4760
|
-
|
|
4819
|
+
if (existingPythonPath) {
|
|
4820
|
+
pathParts.push(existingPythonPath);
|
|
4821
|
+
}
|
|
4822
|
+
env.PYTHONPATH = pathParts.join(import_path7.delimiter);
|
|
4761
4823
|
}
|
|
4762
|
-
const moduleToRun =
|
|
4824
|
+
const moduleToRun = devShim?.module || modulePath;
|
|
4763
4825
|
const pythonArgs = ["-u", "-m", moduleToRun];
|
|
4764
4826
|
const argv = [...spawnArgsPrefix, ...pythonArgs];
|
|
4765
4827
|
(0, import_build_utils8.debug)(
|
|
4766
4828
|
`Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
|
|
4767
4829
|
);
|
|
4830
|
+
if (process.stdout.columns) {
|
|
4831
|
+
env.COLUMNS = `${process.stdout.columns}`;
|
|
4832
|
+
}
|
|
4768
4833
|
const child = (0, import_child_process2.spawn)(spawnCommand, argv, {
|
|
4769
4834
|
cwd: workPath,
|
|
4770
4835
|
env,
|
|
4771
|
-
stdio: ["
|
|
4836
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
4837
|
+
detached: true
|
|
4772
4838
|
});
|
|
4773
4839
|
childProcess = child;
|
|
4774
4840
|
stdoutLogListener = createLogListener(onStdout, process.stdout);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/python",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.17.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"directory": "packages/python"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@vercel/python-analysis": "0.
|
|
18
|
+
"@vercel/python-analysis": "0.8.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@renovatebot/pep440": "4.2.1",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"which": "3.0.0",
|
|
36
36
|
"get-port": "5.1.1",
|
|
37
37
|
"is-port-reachable": "3.1.0",
|
|
38
|
-
"@vercel/
|
|
39
|
-
"@vercel/
|
|
40
|
-
"@vercel/
|
|
38
|
+
"@vercel/build-utils": "13.6.0",
|
|
39
|
+
"@vercel/error-utils": "2.0.3",
|
|
40
|
+
"@vercel/python-runtime": "0.5.2"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "node ../../utils/build-builder.mjs",
|
package/vc_init_dev.py
CHANGED
|
@@ -5,7 +5,7 @@ import sys
|
|
|
5
5
|
import os
|
|
6
6
|
import inspect
|
|
7
7
|
from os import path as _p
|
|
8
|
-
from importlib import
|
|
8
|
+
from importlib import util as _importlib_util
|
|
9
9
|
import mimetypes
|
|
10
10
|
|
|
11
11
|
|
|
@@ -72,8 +72,20 @@ def _strip_service_route_prefix(path_value):
|
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
# ASGI/WSGI app detection
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
_MODULE_NAME = "__VC_DEV_MODULE_NAME__"
|
|
76
|
+
_ENTRY_ABS = "__VC_DEV_ENTRY_ABS__"
|
|
77
|
+
|
|
78
|
+
# Import user module by file path, matching vc_init.py's approach.
|
|
79
|
+
# https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
|
|
80
|
+
_spec = _importlib_util.spec_from_file_location(_MODULE_NAME, _ENTRY_ABS)
|
|
81
|
+
if _spec is None or _spec.loader is None:
|
|
82
|
+
raise RuntimeError(
|
|
83
|
+
f"Could not load module spec for '{_MODULE_NAME}' at {_ENTRY_ABS}"
|
|
84
|
+
)
|
|
85
|
+
_mod = _importlib_util.module_from_spec(_spec)
|
|
86
|
+
sys.modules[_MODULE_NAME] = _mod
|
|
87
|
+
_spec.loader.exec_module(_mod)
|
|
88
|
+
|
|
77
89
|
_user_app_name = (
|
|
78
90
|
"app"
|
|
79
91
|
if hasattr(_mod, "app")
|
|
@@ -83,7 +95,7 @@ _user_app_name = (
|
|
|
83
95
|
)
|
|
84
96
|
if _user_app_name is None:
|
|
85
97
|
raise RuntimeError(
|
|
86
|
-
f"Missing 'app' or 'application' in module '{
|
|
98
|
+
f"Missing 'app' or 'application' in module '{_MODULE_NAME}'. "
|
|
87
99
|
f"Define `app = ...` or `application = ...` in your entrypoint."
|
|
88
100
|
)
|
|
89
101
|
|
|
@@ -137,7 +149,7 @@ def _detect_app_type(app_obj):
|
|
|
137
149
|
|
|
138
150
|
print(
|
|
139
151
|
_color(
|
|
140
|
-
f"Could not determine the application interface for '{
|
|
152
|
+
f"Could not determine the application interface for '{_MODULE_NAME}:{_user_app_name}'\n"
|
|
141
153
|
f"Expected either:\n"
|
|
142
154
|
f" - An ASGI app: async callable(scope, receive, send)\n"
|
|
143
155
|
f" - A WSGI app: callable(environ, start_response)",
|