@vercel/python 25.1.3 → 27.0.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 +102 -99
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -5523,11 +5523,18 @@ var UvRunner = class {
|
|
|
5523
5523
|
}
|
|
5524
5524
|
/**
|
|
5525
5525
|
* Run a `uv pip` command (e.g., `uv pip install`).
|
|
5526
|
+
*
|
|
5527
|
+
* Only packages the builder adds on top of the user's dependencies are
|
|
5528
|
+
* installed this way. Their pins carry no hashes, so the user's
|
|
5529
|
+
* UV_REQUIRE_HASHES is dropped; uv also rejects `--no-require-hashes`
|
|
5530
|
+
* while it is set.
|
|
5526
5531
|
*/
|
|
5527
5532
|
async pip(options) {
|
|
5528
5533
|
const { venvPath, projectDir, args } = options;
|
|
5529
5534
|
const fullArgs = ["pip", ...args];
|
|
5530
|
-
await this.runUvCmd(fullArgs, projectDir, venvPath
|
|
5535
|
+
await this.runUvCmd(fullArgs, projectDir, venvPath, {
|
|
5536
|
+
UV_REQUIRE_HASHES: void 0
|
|
5537
|
+
});
|
|
5531
5538
|
}
|
|
5532
5539
|
/**
|
|
5533
5540
|
* Run a command through `uv run` inside the active virtual environment.
|
|
@@ -5559,13 +5566,13 @@ var UvRunner = class {
|
|
|
5559
5566
|
);
|
|
5560
5567
|
}
|
|
5561
5568
|
}
|
|
5562
|
-
async runUvCmd(args, cwd, venvPath) {
|
|
5569
|
+
async runUvCmd(args, cwd, venvPath, env) {
|
|
5563
5570
|
const pretty = `uv ${args.join(" ")}`;
|
|
5564
5571
|
(0, import_build_utils2.debug)(`Running "${pretty}"...`);
|
|
5565
5572
|
try {
|
|
5566
5573
|
await (0, import_execa2.default)(this.uvPath, args, {
|
|
5567
5574
|
cwd,
|
|
5568
|
-
env: this.getVenvEnv(venvPath)
|
|
5575
|
+
env: { ...this.getVenvEnv(venvPath), ...env }
|
|
5569
5576
|
});
|
|
5570
5577
|
} catch (err) {
|
|
5571
5578
|
const error = new Error(
|
|
@@ -9243,20 +9250,21 @@ async function doInstallInjectedDevPackage(pkg, opts) {
|
|
|
9243
9250
|
`Installing ${pkg.name} into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${dep})`
|
|
9244
9251
|
);
|
|
9245
9252
|
const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
|
|
9246
|
-
const
|
|
9253
|
+
const uvOverrides = uvPath ? ["--exclude-newer-package", `${pkg.name}=false`, "--no-require-hashes"] : [];
|
|
9247
9254
|
const extras = pkg.envOverride || isLocalDev ? [] : pkg.extraRequirements ?? [];
|
|
9248
9255
|
const spawnArgs = [
|
|
9249
9256
|
...pip.prefix,
|
|
9250
9257
|
"--target",
|
|
9251
9258
|
targetDir,
|
|
9252
|
-
...
|
|
9259
|
+
...uvOverrides,
|
|
9253
9260
|
...extras,
|
|
9254
9261
|
dep
|
|
9255
9262
|
];
|
|
9256
9263
|
await new Promise((resolve4, reject) => {
|
|
9257
9264
|
const child = (0, import_child_process2.spawn)(pip.cmd, spawnArgs, {
|
|
9258
9265
|
cwd: workPath,
|
|
9259
|
-
|
|
9266
|
+
// uv rejects `--no-require-hashes` while UV_REQUIRE_HASHES is set.
|
|
9267
|
+
env: { ...getProtectedUvEnv(env), UV_REQUIRE_HASHES: void 0 },
|
|
9260
9268
|
stdio: ["inherit", "pipe", "pipe"]
|
|
9261
9269
|
});
|
|
9262
9270
|
child.stdout?.on("data", (data) => {
|
|
@@ -9407,7 +9415,7 @@ async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath)
|
|
|
9407
9415
|
env.PATH = `${binDir}${import_path13.delimiter}${env.PATH || ""}`;
|
|
9408
9416
|
return { command: pythonBin, args: [] };
|
|
9409
9417
|
}
|
|
9410
|
-
async function
|
|
9418
|
+
async function claimPersistentServer(serverKey, isStale) {
|
|
9411
9419
|
while (true) {
|
|
9412
9420
|
const existing = PERSISTENT_SERVERS.get(serverKey);
|
|
9413
9421
|
if (existing) {
|
|
@@ -9424,9 +9432,19 @@ async function getPersistentServer(serverKey, isStale) {
|
|
|
9424
9432
|
}
|
|
9425
9433
|
const pending = PENDING_STARTS.get(serverKey);
|
|
9426
9434
|
if (!pending)
|
|
9427
|
-
|
|
9435
|
+
break;
|
|
9428
9436
|
await pending;
|
|
9429
9437
|
}
|
|
9438
|
+
let start;
|
|
9439
|
+
const ready = new Promise(
|
|
9440
|
+
(resolve4, reject) => {
|
|
9441
|
+
start = { resolve: resolve4, reject };
|
|
9442
|
+
}
|
|
9443
|
+
);
|
|
9444
|
+
ready.catch(() => {
|
|
9445
|
+
});
|
|
9446
|
+
PENDING_STARTS.set(serverKey, ready);
|
|
9447
|
+
return start;
|
|
9430
9448
|
}
|
|
9431
9449
|
async function spawnPersistentServer({
|
|
9432
9450
|
serverKey,
|
|
@@ -9538,31 +9556,22 @@ var startProxyDevServer = async ({
|
|
|
9538
9556
|
);
|
|
9539
9557
|
}
|
|
9540
9558
|
const serverKey = `${workPath}::proxy::${entrypoint}`;
|
|
9541
|
-
const
|
|
9542
|
-
if (
|
|
9543
|
-
return
|
|
9559
|
+
const start = await claimPersistentServer(serverKey);
|
|
9560
|
+
if ("port" in start) {
|
|
9561
|
+
return start;
|
|
9544
9562
|
}
|
|
9545
9563
|
if (!restoreWarnings)
|
|
9546
9564
|
restoreWarnings = silenceNodeWarnings();
|
|
9547
9565
|
installGlobalCleanupHandlers();
|
|
9548
|
-
const proxySource = (0, import_fs13.readFileSync)((0, import_path13.join)(workPath, entrypoint), "utf8");
|
|
9549
|
-
if (!await (0, import_python_analysis9.containsTopLevelCallable)(proxySource, handlerFunction)) {
|
|
9550
|
-
throw new import_build_utils15.NowBuildError({
|
|
9551
|
-
code: "PYTHON_HANDLER_NOT_FOUND",
|
|
9552
|
-
message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
|
|
9553
|
-
});
|
|
9554
|
-
}
|
|
9555
9566
|
const env = { ...process.env, ...meta.env || {} };
|
|
9556
|
-
let resolveChildReady;
|
|
9557
|
-
let rejectChildReady;
|
|
9558
|
-
const childReady = new Promise(
|
|
9559
|
-
(resolve4, reject) => {
|
|
9560
|
-
resolveChildReady = resolve4;
|
|
9561
|
-
rejectChildReady = reject;
|
|
9562
|
-
}
|
|
9563
|
-
);
|
|
9564
|
-
PENDING_STARTS.set(serverKey, childReady);
|
|
9565
9567
|
try {
|
|
9568
|
+
const proxySource = (0, import_fs13.readFileSync)((0, import_path13.join)(workPath, entrypoint), "utf8");
|
|
9569
|
+
if (!await (0, import_python_analysis9.containsTopLevelCallable)(proxySource, handlerFunction)) {
|
|
9570
|
+
throw new import_build_utils15.NowBuildError({
|
|
9571
|
+
code: "PYTHON_HANDLER_NOT_FOUND",
|
|
9572
|
+
message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
|
|
9573
|
+
});
|
|
9574
|
+
}
|
|
9566
9575
|
const { pythonPath: systemPython } = getDefaultPythonVersion(meta);
|
|
9567
9576
|
const uvPath = await findUvBinary(systemPython);
|
|
9568
9577
|
if (uvPath) {
|
|
@@ -9616,11 +9625,11 @@ var startProxyDevServer = async ({
|
|
|
9616
9625
|
onStdout,
|
|
9617
9626
|
onStderr
|
|
9618
9627
|
});
|
|
9619
|
-
|
|
9628
|
+
start.resolve({ port, pid });
|
|
9620
9629
|
return { port, pid, shutdown: async () => {
|
|
9621
9630
|
} };
|
|
9622
9631
|
} catch (err) {
|
|
9623
|
-
|
|
9632
|
+
start.reject(err);
|
|
9624
9633
|
throw err;
|
|
9625
9634
|
} finally {
|
|
9626
9635
|
PENDING_STARTS.delete(serverKey);
|
|
@@ -9647,83 +9656,74 @@ var startDevServer = async (opts) => {
|
|
|
9647
9656
|
const scheduleEnv = scheduleFunction ? { ...env } : void 0;
|
|
9648
9657
|
const serviceName = service?.name ?? (typeof meta.serviceName === "string" ? meta.serviceName : void 0);
|
|
9649
9658
|
const serverKey = scheduleFunction ? `${workPath}::schedule::${scheduleFunction.outputPath}` : serviceName ? `${workPath}::${framework}::${serviceName}` : `${workPath}::${framework}`;
|
|
9650
|
-
|
|
9659
|
+
if (!framework && !scheduleFunction) {
|
|
9660
|
+
return null;
|
|
9661
|
+
}
|
|
9662
|
+
const start = await claimPersistentServer(
|
|
9651
9663
|
serverKey,
|
|
9652
9664
|
(info) => !!scheduleFunction && (info.scheduleModule !== scheduleModule || !(0, import_util2.isDeepStrictEqual)(info.scheduleEnv, scheduleEnv))
|
|
9653
9665
|
);
|
|
9654
|
-
if (
|
|
9655
|
-
return
|
|
9656
|
-
}
|
|
9657
|
-
if (!framework && !scheduleFunction) {
|
|
9658
|
-
return null;
|
|
9666
|
+
if ("port" in start) {
|
|
9667
|
+
return start;
|
|
9659
9668
|
}
|
|
9660
9669
|
if (!restoreWarnings)
|
|
9661
9670
|
restoreWarnings = silenceNodeWarnings();
|
|
9662
9671
|
installGlobalCleanupHandlers();
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
let hookResult;
|
|
9695
|
-
if (detected?.entrypoint) {
|
|
9696
|
-
resolved = detected.entrypoint;
|
|
9697
|
-
} else if (!isPyprojectEntrypoint) {
|
|
9698
|
-
hookResult = await runFrameworkHook(framework, {
|
|
9699
|
-
pythonEnv: env,
|
|
9700
|
-
workPath,
|
|
9701
|
-
entrypoint,
|
|
9702
|
-
detected: detected ?? void 0
|
|
9703
|
-
});
|
|
9704
|
-
resolved = hookResult?.entrypoint;
|
|
9705
|
-
}
|
|
9706
|
-
if (!resolved) {
|
|
9707
|
-
if (detected?.error) {
|
|
9708
|
-
throw detected.error;
|
|
9672
|
+
try {
|
|
9673
|
+
const entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
|
|
9674
|
+
const isPyprojectEntrypoint = entrypoint === "pyproject.toml";
|
|
9675
|
+
let resolved;
|
|
9676
|
+
const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
|
|
9677
|
+
const isPyQueueSidecar = config?.pythonQueueSidecar === "subscriber" || config?.pythonQueueSidecar === "workflow";
|
|
9678
|
+
let detected;
|
|
9679
|
+
if (scheduleHandlerPath && scheduleModule) {
|
|
9680
|
+
const entrypoint2 = import_path13.posix.join(".vercel/python", scheduleHandlerPath);
|
|
9681
|
+
(0, import_fs13.mkdirSync)((0, import_path13.dirname)((0, import_path13.join)(workPath, entrypoint2)), { recursive: true });
|
|
9682
|
+
(0, import_fs13.writeFileSync)((0, import_path13.join)(workPath, entrypoint2), scheduleModule);
|
|
9683
|
+
detected = { entrypoint: { entrypoint: entrypoint2, variableName: "app" } };
|
|
9684
|
+
} else if (isPyprojectEntrypoint) {
|
|
9685
|
+
const declaredEntrypoint = await getVercelToolsEntrypoint(
|
|
9686
|
+
workPath,
|
|
9687
|
+
opts.repoRootPath
|
|
9688
|
+
);
|
|
9689
|
+
detected = declaredEntrypoint ? { entrypoint: declaredEntrypoint } : null;
|
|
9690
|
+
} else {
|
|
9691
|
+
detected = await detectPythonEntrypoint(
|
|
9692
|
+
framework,
|
|
9693
|
+
workPath,
|
|
9694
|
+
entrypoint ? {
|
|
9695
|
+
filePath: entrypoint,
|
|
9696
|
+
// Schedule-triggered services create their own "app" wrapper dynamically.
|
|
9697
|
+
// Other services use handlerFunction as the entrypoint variable name.
|
|
9698
|
+
varName: service && (0, import_build_utils15.isScheduleTriggeredService)(service) ? void 0 : handlerFunction ?? (isPyQueueSidecar ? "app" : void 0)
|
|
9699
|
+
} : void 0,
|
|
9700
|
+
service,
|
|
9701
|
+
opts.repoRootPath
|
|
9702
|
+
);
|
|
9709
9703
|
}
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
})
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
resolveChildReady = resolve4;
|
|
9722
|
-
rejectChildReady = reject;
|
|
9704
|
+
let hookResult;
|
|
9705
|
+
if (detected?.entrypoint) {
|
|
9706
|
+
resolved = detected.entrypoint;
|
|
9707
|
+
} else if (!isPyprojectEntrypoint) {
|
|
9708
|
+
hookResult = await runFrameworkHook(framework, {
|
|
9709
|
+
pythonEnv: env,
|
|
9710
|
+
workPath,
|
|
9711
|
+
entrypoint,
|
|
9712
|
+
detected: detected ?? void 0
|
|
9713
|
+
});
|
|
9714
|
+
resolved = hookResult?.entrypoint;
|
|
9723
9715
|
}
|
|
9724
|
-
|
|
9725
|
-
|
|
9726
|
-
|
|
9716
|
+
if (!resolved) {
|
|
9717
|
+
if (detected?.error) {
|
|
9718
|
+
throw detected.error;
|
|
9719
|
+
}
|
|
9720
|
+
throw new import_build_utils15.NowBuildError({
|
|
9721
|
+
code: isPyprojectEntrypoint ? "PYTHON_PYPROJECT_NOTHING_TO_BUILD" : "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
9722
|
+
message: isPyprojectEntrypoint ? 'Entrypoint "pyproject.toml" does not declare a web app. Set "tool.vercel.entrypoint" in pyproject.toml.' : "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
9723
|
+
});
|
|
9724
|
+
}
|
|
9725
|
+
const { entrypoint: entry, variableName } = resolved;
|
|
9726
|
+
const modulePath = scheduleHandlerPath ? generatedPythonPathToModule(scheduleHandlerPath) : entrypointToModule(entry);
|
|
9727
9727
|
const { pythonPath: systemPython } = getDefaultPythonVersion(meta);
|
|
9728
9728
|
const uvPath = await findUvBinary(systemPython);
|
|
9729
9729
|
if (uvPath) {
|
|
@@ -9981,12 +9981,12 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
9981
9981
|
scheduleModule,
|
|
9982
9982
|
scheduleEnv
|
|
9983
9983
|
});
|
|
9984
|
-
|
|
9984
|
+
start.resolve({ port, pid });
|
|
9985
9985
|
const shutdown = async () => {
|
|
9986
9986
|
};
|
|
9987
9987
|
return { port, pid, shutdown, crons, queueSubscriptions };
|
|
9988
9988
|
} catch (err) {
|
|
9989
|
-
|
|
9989
|
+
start.reject(err);
|
|
9990
9990
|
throw err;
|
|
9991
9991
|
} finally {
|
|
9992
9992
|
PENDING_STARTS.delete(serverKey);
|
|
@@ -11745,6 +11745,9 @@ async function installInjectedPackage({
|
|
|
11745
11745
|
"install",
|
|
11746
11746
|
"--link-mode",
|
|
11747
11747
|
"copy",
|
|
11748
|
+
// The pin has no hash, so override `require-hashes` from the user's
|
|
11749
|
+
// uv config. `uv.pip` drops UV_REQUIRE_HASHES.
|
|
11750
|
+
"--no-require-hashes",
|
|
11748
11751
|
...pipPlatformArgs,
|
|
11749
11752
|
...noExclude,
|
|
11750
11753
|
...extras,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/python",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "27.0.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"directory": "packages/python"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@vercel/python-analysis": "0.15.
|
|
17
|
+
"@vercel/python-analysis": "0.15.2"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@vercel/build-utils": "14.
|
|
20
|
+
"@vercel/build-utils": "14.23.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@renovatebot/pep440": "4.2.1",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"smol-toml": "1.5.2",
|
|
38
38
|
"vitest": "4.1.10",
|
|
39
39
|
"which": "3.0.0",
|
|
40
|
-
"@vercel/build-utils": "14.
|
|
40
|
+
"@vercel/build-utils": "14.23.0",
|
|
41
41
|
"@vercel/error-utils": "2.2.1",
|
|
42
42
|
"@vercel/python-runtime": "0.23.3"
|
|
43
43
|
},
|