@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.
Files changed (2) hide show
  1. package/dist/index.js +102 -99
  2. 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 excludeOverride = uvPath ? ["--exclude-newer-package", `${pkg.name}=false`] : [];
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
- ...excludeOverride,
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
- env: getProtectedUvEnv(env),
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 getPersistentServer(serverKey, isStale) {
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
- return null;
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 existing = await getPersistentServer(serverKey);
9542
- if (existing) {
9543
- return existing;
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
- resolveChildReady({ port, pid });
9628
+ start.resolve({ port, pid });
9620
9629
  return { port, pid, shutdown: async () => {
9621
9630
  } };
9622
9631
  } catch (err) {
9623
- rejectChildReady(err);
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
- const existing = await getPersistentServer(
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 (existing) {
9655
- return existing;
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
- const entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
9664
- const isPyprojectEntrypoint = entrypoint === "pyproject.toml";
9665
- let resolved;
9666
- const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
9667
- const isPyQueueSidecar = config?.pythonQueueSidecar === "subscriber" || config?.pythonQueueSidecar === "workflow";
9668
- let detected;
9669
- if (scheduleHandlerPath && scheduleModule) {
9670
- const entrypoint2 = import_path13.posix.join(".vercel/python", scheduleHandlerPath);
9671
- (0, import_fs13.mkdirSync)((0, import_path13.dirname)((0, import_path13.join)(workPath, entrypoint2)), { recursive: true });
9672
- (0, import_fs13.writeFileSync)((0, import_path13.join)(workPath, entrypoint2), scheduleModule);
9673
- detected = { entrypoint: { entrypoint: entrypoint2, variableName: "app" } };
9674
- } else if (isPyprojectEntrypoint) {
9675
- const declaredEntrypoint = await getVercelToolsEntrypoint(
9676
- workPath,
9677
- opts.repoRootPath
9678
- );
9679
- detected = declaredEntrypoint ? { entrypoint: declaredEntrypoint } : null;
9680
- } else {
9681
- detected = await detectPythonEntrypoint(
9682
- framework,
9683
- workPath,
9684
- entrypoint ? {
9685
- filePath: entrypoint,
9686
- // Schedule-triggered services create their own "app" wrapper dynamically.
9687
- // Other services use handlerFunction as the entrypoint variable name.
9688
- varName: service && (0, import_build_utils15.isScheduleTriggeredService)(service) ? void 0 : handlerFunction ?? (isPyQueueSidecar ? "app" : void 0)
9689
- } : void 0,
9690
- service,
9691
- opts.repoRootPath
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
- throw new import_build_utils15.NowBuildError({
9711
- code: isPyprojectEntrypoint ? "PYTHON_PYPROJECT_NOTHING_TO_BUILD" : "PYTHON_ENTRYPOINT_NOT_FOUND",
9712
- 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."
9713
- });
9714
- }
9715
- const { entrypoint: entry, variableName } = resolved;
9716
- const modulePath = scheduleHandlerPath ? generatedPythonPathToModule(scheduleHandlerPath) : entrypointToModule(entry);
9717
- let resolveChildReady;
9718
- let rejectChildReady;
9719
- const childReady = new Promise(
9720
- (resolve4, reject) => {
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
- PENDING_STARTS.set(serverKey, childReady);
9726
- try {
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
- resolveChildReady({ port, pid });
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
- rejectChildReady(err);
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": "25.1.3",
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.0"
17
+ "@vercel/python-analysis": "0.15.2"
18
18
  },
19
19
  "peerDependencies": {
20
- "@vercel/build-utils": "14.21.3"
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.21.3",
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
  },