@vercel/python 25.0.0 → 25.1.2

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 +382 -163
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -5032,7 +5032,7 @@ var import_fs20 = __toESM(require("fs"));
5032
5032
  var import_path21 = require("path");
5033
5033
 
5034
5034
  // src/package-versions.ts
5035
- var VERCEL_RUNTIME_VERSION = "0.23.2";
5035
+ var VERCEL_RUNTIME_VERSION = "0.23.3";
5036
5036
  var VERCEL_WORKERS_VERSION = "0.0.25";
5037
5037
 
5038
5038
  // src/conditional-vendoring.ts
@@ -5366,12 +5366,13 @@ var import_execa4 = __toESM(require_execa());
5366
5366
  var import_fs5 = __toESM(require("fs"));
5367
5367
  var import_path6 = require("path");
5368
5368
  var import_build_utils6 = require("@vercel/build-utils");
5369
- var import_python_analysis4 = require("@vercel/python-analysis");
5369
+ var import_python_analysis5 = require("@vercel/python-analysis");
5370
5370
 
5371
5371
  // src/utils.ts
5372
5372
  var import_fs3 = __toESM(require("fs"));
5373
5373
  var import_path4 = require("path");
5374
5374
  var import_build_utils3 = require("@vercel/build-utils");
5375
+ var import_python_analysis3 = require("@vercel/python-analysis");
5375
5376
  var import_execa3 = __toESM(require_execa());
5376
5377
 
5377
5378
  // src/uv.ts
@@ -5956,6 +5957,22 @@ async function ensureVenv({
5956
5957
  await (0, import_execa3.default)(pythonVersion.pythonPath, ["-m", "venv", venvPath]);
5957
5958
  }
5958
5959
  }
5960
+ var BUILD_ONLY_SEED_PACKAGES = ["pip"];
5961
+ async function getSeedPackagesMissingFromLock(uvLockPath) {
5962
+ let lockedPackages;
5963
+ try {
5964
+ const content = await import_fs3.default.promises.readFile(uvLockPath, "utf8");
5965
+ lockedPackages = new Set(
5966
+ (0, import_python_analysis3.parseUvLock)(content, uvLockPath).packages.map(
5967
+ (pkg) => (0, import_python_analysis3.normalizePackageName)(pkg.name)
5968
+ )
5969
+ );
5970
+ } catch (err) {
5971
+ (0, import_build_utils3.debug)(`could not read lock file "${uvLockPath}" for seed packages: ${err}`);
5972
+ return [];
5973
+ }
5974
+ return BUILD_ONLY_SEED_PACKAGES.filter((name) => !lockedPackages.has(name));
5975
+ }
5959
5976
  function getVenvPythonBin(venvPath) {
5960
5977
  return (0, import_path4.join)(getVenvBinDir(venvPath), isWin2 ? "python.exe" : "python");
5961
5978
  }
@@ -5996,7 +6013,7 @@ async function runPyprojectScript(workPath, scriptNames, env, useUserVirtualEnv
5996
6013
  var import_path5 = require("path");
5997
6014
  var import_fs4 = require("fs");
5998
6015
  var import_build_utils5 = require("@vercel/build-utils");
5999
- var import_python_analysis3 = require("@vercel/python-analysis");
6016
+ var import_python_analysis4 = require("@vercel/python-analysis");
6000
6017
 
6001
6018
  // src/platform-info.ts
6002
6019
  var import_os2 = __toESM(require("os"));
@@ -6207,7 +6224,7 @@ function resolvePythonVersion({
6207
6224
  const defaultBuild = toPythonBuild(defaultPv);
6208
6225
  const availableBuilds = getAvailablePythonBuilds();
6209
6226
  const allBuilds = getAllPythonBuilds();
6210
- const result = (0, import_python_analysis3.selectPythonVersion)({
6227
+ const result = (0, import_python_analysis4.selectPythonVersion)({
6211
6228
  constraints,
6212
6229
  availableBuilds,
6213
6230
  allBuilds,
@@ -6266,7 +6283,7 @@ function resolvePythonVersion({
6266
6283
  }
6267
6284
  let pinVersionFilePath;
6268
6285
  const hasPythonVersionFile = pythonPackage.configs?.some(
6269
- (configSet) => configSet[import_python_analysis3.PythonConfigKind.PythonVersion] !== void 0
6286
+ (configSet) => configSet[import_python_analysis4.PythonConfigKind.PythonVersion] !== void 0
6270
6287
  ) ?? false;
6271
6288
  if (!hasPythonVersionFile && pythonPackage.manifest && versionLessOrEqual(selection, defaultPv)) {
6272
6289
  if (autoUpgraded || !pythonPackage.manifest.origin && source?.endsWith("pyproject.toml")) {
@@ -6425,9 +6442,9 @@ async function discoverPackage({
6425
6442
  rootDir
6426
6443
  }) {
6427
6444
  try {
6428
- return await (0, import_python_analysis4.discoverPythonPackage)({ entrypointDir, rootDir });
6445
+ return await (0, import_python_analysis5.discoverPythonPackage)({ entrypointDir, rootDir });
6429
6446
  } catch (error) {
6430
- if (error instanceof import_python_analysis4.PythonAnalysisError) {
6447
+ if (error instanceof import_python_analysis5.PythonAnalysisError) {
6431
6448
  if (error.fileContent && (error.code.endsWith("_PARSE_ERROR") || error.code.endsWith("_VALIDATION_ERROR"))) {
6432
6449
  console.log(
6433
6450
  `Failed to parse "${error.path}". File content:
@@ -6449,10 +6466,10 @@ function detectInstallSource(pythonPackage, rootDir) {
6449
6466
  let manifestPath = null;
6450
6467
  const lockFile = pythonPackage.manifest?.lockFile ?? pythonPackage.workspaceLockFile;
6451
6468
  if (lockFile) {
6452
- if (lockFile.kind === import_python_analysis4.PythonLockFileKind.UvLock) {
6469
+ if (lockFile.kind === import_python_analysis5.PythonLockFileKind.UvLock) {
6453
6470
  manifestType = "uv.lock";
6454
6471
  manifestPath = (0, import_path6.join)(rootDir, lockFile.path);
6455
- } else if (lockFile.kind === import_python_analysis4.PythonLockFileKind.PylockToml) {
6472
+ } else if (lockFile.kind === import_python_analysis5.PythonLockFileKind.PylockToml) {
6456
6473
  manifestType = "pylock.toml";
6457
6474
  manifestPath = (0, import_path6.join)(rootDir, lockFile.path);
6458
6475
  }
@@ -6499,11 +6516,11 @@ async function ensureUvProject({
6499
6516
  projectDir = (0, import_path6.join)(rootDir, (0, import_path6.dirname)(manifest.path));
6500
6517
  pyprojectPath = (0, import_path6.join)(rootDir, manifest.path);
6501
6518
  const originKind = manifest.origin?.kind;
6502
- if (originKind === import_python_analysis4.PythonManifestConvertedKind.Pipfile) {
6519
+ if (originKind === import_python_analysis5.PythonManifestConvertedKind.Pipfile) {
6503
6520
  console.log("Installing required dependencies from Pipfile...");
6504
- } else if (originKind === import_python_analysis4.PythonManifestConvertedKind.PipfileLock) {
6521
+ } else if (originKind === import_python_analysis5.PythonManifestConvertedKind.PipfileLock) {
6505
6522
  console.log("Installing required dependencies from Pipfile.lock...");
6506
- } else if (originKind === import_python_analysis4.PythonManifestConvertedKind.RequirementsTxt || originKind === import_python_analysis4.PythonManifestConvertedKind.RequirementsIn) {
6523
+ } else if (originKind === import_python_analysis5.PythonManifestConvertedKind.RequirementsTxt || originKind === import_python_analysis5.PythonManifestConvertedKind.RequirementsIn) {
6507
6524
  console.log(
6508
6525
  `Installing required dependencies from ${manifest.origin?.path ?? "requirements.txt"}...`
6509
6526
  );
@@ -6514,7 +6531,7 @@ async function ensureUvProject({
6514
6531
  if (manifest.data.project && pythonVersion !== void 0) {
6515
6532
  manifest.data.project["requires-python"] = `~=${pythonVersion}.0`;
6516
6533
  }
6517
- const content = (0, import_python_analysis4.stringifyManifest)(manifest.data);
6534
+ const content = (0, import_python_analysis5.stringifyManifest)(manifest.data);
6518
6535
  pyprojectPath = (0, import_path6.join)(projectDir, "pyproject.toml");
6519
6536
  await import_fs5.default.promises.writeFile(pyprojectPath, content);
6520
6537
  }
@@ -6537,12 +6554,12 @@ async function ensureUvProject({
6537
6554
  "No Python manifest found; creating an empty pyproject.toml and uv.lock..."
6538
6555
  );
6539
6556
  const requiresPython = pythonVersion !== void 0 ? `~=${pythonVersion}.0` : `>=${DEFAULT_PYTHON_VERSION_STRING}`;
6540
- const minimalManifest = (0, import_python_analysis4.createMinimalManifest)({
6557
+ const minimalManifest = (0, import_python_analysis5.createMinimalManifest)({
6541
6558
  name: "app",
6542
6559
  requiresPython,
6543
6560
  dependencies: []
6544
6561
  });
6545
- const content = (0, import_python_analysis4.stringifyManifest)(minimalManifest);
6562
+ const content = (0, import_python_analysis5.stringifyManifest)(minimalManifest);
6546
6563
  await import_fs5.default.promises.writeFile(pyprojectPath, content);
6547
6564
  await restoreCachedLock(cachedLockPath, projectDir);
6548
6565
  await uv.lock({
@@ -6656,7 +6673,7 @@ var import_fs6 = __toESM(require("fs"));
6656
6673
  var import_util = require("util");
6657
6674
  var import_path7 = require("path");
6658
6675
  var import_build_utils7 = require("@vercel/build-utils");
6659
- var import_python_analysis5 = require("@vercel/python-analysis");
6676
+ var import_python_analysis6 = require("@vercel/python-analysis");
6660
6677
 
6661
6678
  // src/large-functions.ts
6662
6679
  function isLargeFunctionsEnabled() {
@@ -6818,9 +6835,9 @@ smaller functions.`,
6818
6835
  }
6819
6836
  let lockFile;
6820
6837
  try {
6821
- lockFile = (0, import_python_analysis5.parseUvLock)(lockContent, relLockPath);
6838
+ lockFile = (0, import_python_analysis6.parseUvLock)(lockContent, relLockPath);
6822
6839
  } catch (error) {
6823
- if (error instanceof import_python_analysis5.PythonAnalysisError) {
6840
+ if (error instanceof import_python_analysis6.PythonAnalysisError) {
6824
6841
  if (error.fileContent) {
6825
6842
  (0, import_build_utils7.debug)(
6826
6843
  `Failed to parse "${error.path}". File content:
@@ -6841,7 +6858,7 @@ ${error.fileContent}`
6841
6858
  `Excluding project package "${this.projectName}" from runtime installation`
6842
6859
  );
6843
6860
  }
6844
- const classification = (0, import_python_analysis5.classifyPackages)({
6861
+ const classification = (0, import_python_analysis6.classifyPackages)({
6845
6862
  lockFile,
6846
6863
  excludePackages
6847
6864
  });
@@ -6858,10 +6875,10 @@ ${error.fileContent}`
6858
6875
  );
6859
6876
  }
6860
6877
  const forceBundledSet = new Set(
6861
- forceBundledDueToWheels.map(import_python_analysis5.normalizePackageName)
6878
+ forceBundledDueToWheels.map(import_python_analysis6.normalizePackageName)
6862
6879
  );
6863
6880
  const externalizablePublic = classification.publicPackages.filter(
6864
- (name) => !forceBundledSet.has((0, import_python_analysis5.normalizePackageName)(name))
6881
+ (name) => !forceBundledSet.has((0, import_python_analysis6.normalizePackageName)(name))
6865
6882
  );
6866
6883
  if (externalizablePublic.length === 0) {
6867
6884
  if (largeFunctionsEnabled) {
@@ -6927,11 +6944,11 @@ To fix this, either:
6927
6944
  `Bundle size (${totalBundleSizeMB} MB) exceeds the standard size; optimizing dependencies.`
6928
6945
  );
6929
6946
  const externalizableSet = new Set(
6930
- externalizablePublic.map(import_python_analysis5.normalizePackageName)
6947
+ externalizablePublic.map(import_python_analysis6.normalizePackageName)
6931
6948
  );
6932
6949
  const publicPackageSizes = new Map(
6933
6950
  [...packageSizes].filter(
6934
- ([name]) => externalizableSet.has((0, import_python_analysis5.normalizePackageName)(name))
6951
+ ([name]) => externalizableSet.has((0, import_python_analysis6.normalizePackageName)(name))
6935
6952
  )
6936
6953
  );
6937
6954
  const { packingMode, bundledPublic } = planPublicPackagePacking({
@@ -6944,9 +6961,9 @@ To fix this, either:
6944
6961
  `bytecode-first packing disabled: the public package set exceeds the ephemeral install budget (${(EPHEMERAL_INSTALL_BUDGET_BYTES / (1024 * 1024)).toFixed(2)} MB); falling back to knapsack packing`
6945
6962
  );
6946
6963
  }
6947
- const bundledPublicSet = new Set(bundledPublic.map(import_python_analysis5.normalizePackageName));
6964
+ const bundledPublicSet = new Set(bundledPublic.map(import_python_analysis6.normalizePackageName));
6948
6965
  const externalizedPublic = externalizablePublic.filter(
6949
- (name) => !bundledPublicSet.has((0, import_python_analysis5.normalizePackageName)(name))
6966
+ (name) => !bundledPublicSet.has((0, import_python_analysis6.normalizePackageName)(name))
6950
6967
  );
6951
6968
  const allBundledPackages = [...alwaysBundled, ...bundledPublic];
6952
6969
  const selectedVendorFiles = await this.installedDistributions.mirrorPackagesIntoVendor({
@@ -7084,24 +7101,24 @@ functions.`,
7084
7101
  platform.archName
7085
7102
  );
7086
7103
  const relevantPackages = reachable ? publicPackageNames.filter(
7087
- (name) => reachable.has((0, import_python_analysis5.normalizePackageName)(name))
7104
+ (name) => reachable.has((0, import_python_analysis6.normalizePackageName)(name))
7088
7105
  ) : publicPackageNames;
7089
7106
  if (relevantPackages.length < publicPackageNames.length) {
7090
7107
  (0, import_build_utils7.debug)(
7091
7108
  `Skipping wheel check for ${publicPackageNames.length - relevantPackages.length} package(s) not reachable on the target platform`
7092
7109
  );
7093
7110
  }
7094
- const publicSet = new Set(relevantPackages.map(import_python_analysis5.normalizePackageName));
7111
+ const publicSet = new Set(relevantPackages.map(import_python_analysis6.normalizePackageName));
7095
7112
  const packageWheels = /* @__PURE__ */ new Map();
7096
7113
  for (const pkg of lockFile.packages) {
7097
- const normalized = (0, import_python_analysis5.normalizePackageName)(pkg.name);
7114
+ const normalized = (0, import_python_analysis6.normalizePackageName)(pkg.name);
7098
7115
  if (publicSet.has(normalized) && pkg.wheels.length > 0) {
7099
7116
  packageWheels.set(normalized, pkg.wheels);
7100
7117
  }
7101
7118
  }
7102
7119
  const incompatible = [];
7103
7120
  for (const name of relevantPackages) {
7104
- const normalized = (0, import_python_analysis5.normalizePackageName)(name);
7121
+ const normalized = (0, import_python_analysis6.normalizePackageName)(name);
7105
7122
  const wheels = packageWheels.get(normalized);
7106
7123
  if (!wheels || wheels.length === 0) {
7107
7124
  incompatible.push(name);
@@ -7113,7 +7130,7 @@ functions.`,
7113
7130
  if (!filename || !filename.endsWith(".whl"))
7114
7131
  continue;
7115
7132
  try {
7116
- const compatible = await (0, import_python_analysis5.isWheelCompatible)(
7133
+ const compatible = await (0, import_python_analysis6.isWheelCompatible)(
7117
7134
  filename,
7118
7135
  this.pythonVersion.major,
7119
7136
  this.pythonVersion.minor,
@@ -7151,10 +7168,10 @@ functions.`,
7151
7168
  async function getPackagesReachableOnPlatform(lockFile, projectName, pythonMajor, pythonMinor, sysPlatform, platformMachine) {
7152
7169
  if (!projectName)
7153
7170
  return null;
7154
- const rootNormalized = (0, import_python_analysis5.normalizePackageName)(projectName);
7171
+ const rootNormalized = (0, import_python_analysis6.normalizePackageName)(projectName);
7155
7172
  const packageMap = /* @__PURE__ */ new Map();
7156
7173
  for (const pkg of lockFile.packages) {
7157
- packageMap.set((0, import_python_analysis5.normalizePackageName)(pkg.name), pkg);
7174
+ packageMap.set((0, import_python_analysis6.normalizePackageName)(pkg.name), pkg);
7158
7175
  }
7159
7176
  const rootPkg = packageMap.get(rootNormalized);
7160
7177
  if (!rootPkg)
@@ -7166,12 +7183,12 @@ async function getPackagesReachableOnPlatform(lockFile, projectName, pythonMajor
7166
7183
  if (!pkg.dependencies)
7167
7184
  return;
7168
7185
  for (const dep of pkg.dependencies) {
7169
- const normalized = (0, import_python_analysis5.normalizePackageName)(dep.name);
7186
+ const normalized = (0, import_python_analysis6.normalizePackageName)(dep.name);
7170
7187
  if (visited.has(normalized))
7171
7188
  continue;
7172
7189
  if (dep.marker) {
7173
7190
  try {
7174
- const compatible = await (0, import_python_analysis5.evaluateMarker)(
7191
+ const compatible = await (0, import_python_analysis6.evaluateMarker)(
7175
7192
  dep.marker,
7176
7193
  pythonMajor,
7177
7194
  pythonMinor,
@@ -7278,7 +7295,7 @@ function planPublicPackagePacking({
7278
7295
  // src/diagnostics.ts
7279
7296
  var import_fs7 = __toESM(require("fs"));
7280
7297
  var import_build_utils8 = require("@vercel/build-utils");
7281
- var import_python_analysis6 = require("@vercel/python-analysis");
7298
+ var import_python_analysis7 = require("@vercel/python-analysis");
7282
7299
  function isDependencyGroupInclude(entry) {
7283
7300
  return typeof entry === "object" && "include-group" in entry;
7284
7301
  }
@@ -7371,13 +7388,13 @@ async function generateProjectManifest({
7371
7388
  allRawDeps.push({ dep, scope: "dev" });
7372
7389
  }
7373
7390
  }
7374
- const allParsed = await (0, import_python_analysis6.parsePep508)(allRawDeps.map((d) => d.dep));
7391
+ const allParsed = await (0, import_python_analysis7.parsePep508)(allRawDeps.map((d) => d.dep));
7375
7392
  for (let i = 0; i < allRawDeps.length; i++) {
7376
7393
  const parsed = allParsed[i];
7377
7394
  if (!parsed)
7378
7395
  continue;
7379
7396
  const { dep, scope } = allRawDeps[i];
7380
- const normalized = (0, import_python_analysis6.normalizePackageName)(parsed.name);
7397
+ const normalized = (0, import_python_analysis7.normalizePackageName)(parsed.name);
7381
7398
  let scopes = directScopesMap.get(normalized);
7382
7399
  if (!scopes) {
7383
7400
  scopes = /* @__PURE__ */ new Set();
@@ -7392,15 +7409,15 @@ async function generateProjectManifest({
7392
7409
  const transitiveEntries = [];
7393
7410
  {
7394
7411
  const content = await import_fs7.default.promises.readFile(uvLockPath, "utf-8");
7395
- const uvLock = (0, import_python_analysis6.parseUvLock)(content, uvLockPath);
7412
+ const uvLock = (0, import_python_analysis7.parseUvLock)(content, uvLockPath);
7396
7413
  const projectName = project?.name;
7397
7414
  const excludeSet = new Set(
7398
- projectName ? [(0, import_python_analysis6.normalizePackageName)(projectName)] : []
7415
+ projectName ? [(0, import_python_analysis7.normalizePackageName)(projectName)] : []
7399
7416
  );
7400
7417
  const lockMap = /* @__PURE__ */ new Map();
7401
7418
  const depGraph = /* @__PURE__ */ new Map();
7402
7419
  for (const pkg of uvLock.packages) {
7403
- const normalized = (0, import_python_analysis6.normalizePackageName)(pkg.name);
7420
+ const normalized = (0, import_python_analysis7.normalizePackageName)(pkg.name);
7404
7421
  if (excludeSet.has(normalized))
7405
7422
  continue;
7406
7423
  if (pkg.source?.virtual)
@@ -7409,7 +7426,7 @@ async function generateProjectManifest({
7409
7426
  if (pkg.dependencies) {
7410
7427
  const deps = /* @__PURE__ */ new Set();
7411
7428
  for (const d of pkg.dependencies) {
7412
- deps.add((0, import_python_analysis6.normalizePackageName)(d.name));
7429
+ deps.add((0, import_python_analysis7.normalizePackageName)(d.name));
7413
7430
  }
7414
7431
  depGraph.set(normalized, deps);
7415
7432
  }
@@ -7512,7 +7529,7 @@ var import_path8 = require("path");
7512
7529
  var import_build_utils9 = require("@vercel/build-utils");
7513
7530
  var import_build_utils10 = require("@vercel/build-utils");
7514
7531
  var import_build_utils11 = require("@vercel/build-utils");
7515
- var import_python_analysis7 = require("@vercel/python-analysis");
7532
+ var import_python_analysis8 = require("@vercel/python-analysis");
7516
7533
  var PYTHON_ENTRYPOINT_FILENAMES = [
7517
7534
  "app",
7518
7535
  "index",
@@ -7595,7 +7612,7 @@ async function checkEntrypoint(workPath, relPath) {
7595
7612
  if (!await fileExists(absPath))
7596
7613
  return null;
7597
7614
  const content = await import_fs8.default.promises.readFile(absPath, "utf-8");
7598
- return (0, import_python_analysis7.findAppOrHandler)(content);
7615
+ return (0, import_python_analysis8.findAppOrHandler)(content);
7599
7616
  }
7600
7617
  async function findPythonFilesRecursive(dir, rootDir) {
7601
7618
  const results = [];
@@ -7626,7 +7643,7 @@ async function findEntrypointCandidates(workPath) {
7626
7643
  (0, import_path8.join)(workPath, relPath),
7627
7644
  "utf-8"
7628
7645
  );
7629
- const varName = await (0, import_python_analysis7.findAppOrHandler)(content);
7646
+ const varName = await (0, import_python_analysis8.findAppOrHandler)(content);
7630
7647
  if (varName) {
7631
7648
  candidates.push({ entrypoint: relPath, variableName: varName });
7632
7649
  }
@@ -7725,7 +7742,7 @@ async function findValidEntrypoint(workPath, candidates) {
7725
7742
  if (!await fileExists(absPath))
7726
7743
  continue;
7727
7744
  const content = await import_fs8.default.promises.readFile(absPath, "utf-8");
7728
- const varName = await (0, import_python_analysis7.findAppOrHandler)(content);
7745
+ const varName = await (0, import_python_analysis8.findAppOrHandler)(content);
7729
7746
  if (varName) {
7730
7747
  (0, import_build_utils10.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
7731
7748
  return {
@@ -8120,7 +8137,7 @@ var import_util2 = require("util");
8120
8137
  var import_build_utils15 = require("@vercel/build-utils");
8121
8138
  var import_get_port = __toESM(require_get_port());
8122
8139
  var import_is_port_reachable = __toESM(require_is_port_reachable());
8123
- var import_python_analysis8 = require("@vercel/python-analysis");
8140
+ var import_python_analysis9 = require("@vercel/python-analysis");
8124
8141
 
8125
8142
  // src/subscribers.ts
8126
8143
  var import_path12 = require("path");
@@ -9017,12 +9034,18 @@ async function syncDependencies({
9017
9034
  pythonBin,
9018
9035
  env,
9019
9036
  onStdout,
9020
- onStderr
9037
+ onStderr,
9038
+ onlyGroup,
9039
+ activeVenv
9021
9040
  }) {
9022
9041
  const pythonPackage = await discoverPackage({
9023
9042
  entrypointDir: workPath,
9024
9043
  rootDir: workPath
9025
9044
  });
9045
+ if (onlyGroup && !(onlyGroup in (pythonPackage.manifest?.data?.["dependency-groups"] ?? {}))) {
9046
+ (0, import_build_utils15.debug)(`No "${onlyGroup}" dependency group found, skipping dependency sync`);
9047
+ return;
9048
+ }
9026
9049
  const installInfo = detectInstallSource(pythonPackage, workPath);
9027
9050
  const { manifestType } = installInfo;
9028
9051
  let { manifestPath } = installInfo;
@@ -9035,7 +9058,7 @@ async function syncDependencies({
9035
9058
  const syncDir = (0, import_path13.join)(workPath, ".vercel", "python", "sync");
9036
9059
  (0, import_fs13.mkdirSync)(syncDir, { recursive: true });
9037
9060
  const tempPyproject = (0, import_path13.join)(syncDir, "pyproject.toml");
9038
- const content = (0, import_python_analysis8.stringifyManifest)(manifest.data);
9061
+ const content = (0, import_python_analysis9.stringifyManifest)(manifest.data);
9039
9062
  (0, import_fs13.writeFileSync)(tempPyproject, content, "utf8");
9040
9063
  manifestPath = tempPyproject;
9041
9064
  (0, import_build_utils15.debug)(
@@ -9064,6 +9087,8 @@ async function syncDependencies({
9064
9087
  uvPath,
9065
9088
  pythonBin,
9066
9089
  env,
9090
+ onlyGroup,
9091
+ activeVenv,
9067
9092
  onStdout: (data) => captured.push(["stdout", data]),
9068
9093
  onStderr: (data) => captured.push(["stderr", data])
9069
9094
  });
@@ -9083,6 +9108,8 @@ async function runSync({
9083
9108
  uvPath,
9084
9109
  pythonBin,
9085
9110
  env,
9111
+ onlyGroup,
9112
+ activeVenv,
9086
9113
  onStdout,
9087
9114
  onStderr
9088
9115
  }) {
@@ -9102,16 +9129,32 @@ async function runSync({
9102
9129
  }
9103
9130
  spawnCmd = uvPath;
9104
9131
  spawnArgs = ["sync"];
9132
+ if (activeVenv) {
9133
+ spawnArgs.push("--active");
9134
+ }
9135
+ if (onlyGroup) {
9136
+ spawnArgs.push("--only-group", onlyGroup, "--no-install-project");
9137
+ }
9105
9138
  break;
9106
9139
  }
9107
9140
  case "pylock.toml": {
9108
9141
  spawnCmd = pip.cmd;
9109
- spawnArgs = [...pip.prefix, "-r", manifestPath];
9142
+ spawnArgs = [...pip.prefix];
9143
+ if (onlyGroup) {
9144
+ spawnArgs.push("--group", onlyGroup);
9145
+ } else {
9146
+ spawnArgs.push("-r", manifestPath);
9147
+ }
9110
9148
  break;
9111
9149
  }
9112
9150
  case "pyproject.toml": {
9113
9151
  spawnCmd = pip.cmd;
9114
- spawnArgs = [...pip.prefix, projectDir];
9152
+ spawnArgs = [...pip.prefix];
9153
+ if (onlyGroup) {
9154
+ spawnArgs.push("--group", onlyGroup);
9155
+ } else {
9156
+ spawnArgs.push(projectDir);
9157
+ }
9115
9158
  break;
9116
9159
  }
9117
9160
  default:
@@ -9364,7 +9407,229 @@ async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath)
9364
9407
  env.PATH = `${binDir}${import_path13.delimiter}${env.PATH || ""}`;
9365
9408
  return { command: pythonBin, args: [] };
9366
9409
  }
9410
+ async function getPersistentServer(serverKey, isStale) {
9411
+ while (true) {
9412
+ const existing = PERSISTENT_SERVERS.get(serverKey);
9413
+ if (existing) {
9414
+ if (isStale?.(existing)) {
9415
+ killPersistentServer(serverKey);
9416
+ } else {
9417
+ return {
9418
+ port: existing.port,
9419
+ pid: existing.pid,
9420
+ shutdown: async () => {
9421
+ }
9422
+ };
9423
+ }
9424
+ }
9425
+ const pending = PENDING_STARTS.get(serverKey);
9426
+ if (!pending)
9427
+ return null;
9428
+ await pending;
9429
+ }
9430
+ }
9431
+ async function spawnPersistentServer({
9432
+ serverKey,
9433
+ workPath,
9434
+ entry,
9435
+ modulePath,
9436
+ shimSubdir,
9437
+ framework,
9438
+ variableName,
9439
+ extraPythonPath,
9440
+ spawnCommand,
9441
+ spawnArgsPrefix,
9442
+ port: requestedPort,
9443
+ env,
9444
+ onStdout,
9445
+ onStderr,
9446
+ scheduleModule,
9447
+ scheduleEnv
9448
+ }) {
9449
+ const port = requestedPort ?? await (0, import_get_port.default)();
9450
+ env.PORT = `${port}`;
9451
+ if (entry) {
9452
+ env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path13.join)(workPath, entry);
9453
+ }
9454
+ const devShim = createDevShim(
9455
+ workPath,
9456
+ entry,
9457
+ modulePath,
9458
+ shimSubdir,
9459
+ framework,
9460
+ variableName
9461
+ );
9462
+ if (devShim) {
9463
+ const shimDir = devShim.shimDir || (0, import_path13.join)(workPath, ".vercel", "python");
9464
+ const runtimeDir = (0, import_path13.join)(workPath, ".vercel", "python");
9465
+ const pathParts = shimDir !== runtimeDir ? [shimDir, runtimeDir] : [shimDir];
9466
+ if (devShim.extraPythonPath) {
9467
+ pathParts.push(devShim.extraPythonPath);
9468
+ }
9469
+ if (extraPythonPath) {
9470
+ pathParts.push(extraPythonPath);
9471
+ }
9472
+ const existingPythonPath = env.PYTHONPATH || "";
9473
+ if (existingPythonPath) {
9474
+ pathParts.push(existingPythonPath);
9475
+ }
9476
+ env.PYTHONPATH = pathParts.join(import_path13.delimiter);
9477
+ }
9478
+ const moduleToRun = devShim?.module || modulePath;
9479
+ const pythonArgs = ["-u", "-m", moduleToRun];
9480
+ const argv = [...spawnArgsPrefix, ...pythonArgs];
9481
+ (0, import_build_utils15.debug)(
9482
+ `Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
9483
+ );
9484
+ if (process.stdout.columns) {
9485
+ env.COLUMNS = `${process.stdout.columns}`;
9486
+ }
9487
+ const child = (0, import_child_process2.spawn)(spawnCommand, argv, {
9488
+ cwd: workPath,
9489
+ env,
9490
+ stdio: ["ignore", "pipe", "pipe"],
9491
+ detached: true
9492
+ });
9493
+ const stdoutLogListener = createLogListener(onStdout, process.stdout);
9494
+ const stderrLogListener = createLogListener(onStderr, process.stderr);
9495
+ child.stdout?.on("data", stdoutLogListener);
9496
+ child.stderr?.on("data", stderrLogListener);
9497
+ const childExited = new Promise((_resolve, reject) => {
9498
+ child.once("error", (err) => {
9499
+ reject(err);
9500
+ });
9501
+ child.once("exit", (code, signal) => {
9502
+ reject(
9503
+ new Error(
9504
+ `Python dev server exited before binding (code=${code}, signal=${signal})`
9505
+ )
9506
+ );
9507
+ });
9508
+ });
9509
+ await Promise.race([
9510
+ checkForPort(port, DEV_SERVER_STARTUP_TIMEOUT),
9511
+ childExited
9512
+ ]);
9513
+ const pid = child.pid;
9514
+ PERSISTENT_SERVERS.set(serverKey, {
9515
+ port,
9516
+ pid,
9517
+ child,
9518
+ stdoutLogListener,
9519
+ stderrLogListener,
9520
+ scheduleModule,
9521
+ scheduleEnv
9522
+ });
9523
+ return { port, pid };
9524
+ }
9525
+ var PROXY_DEPENDENCY_GROUP = "vercel.proxy";
9526
+ var startProxyDevServer = async ({
9527
+ entrypoint,
9528
+ workPath,
9529
+ meta = {},
9530
+ config,
9531
+ onStdout,
9532
+ onStderr
9533
+ }) => {
9534
+ const handlerFunction = config?.handlerFunction;
9535
+ if (typeof handlerFunction !== "string" || !handlerFunction) {
9536
+ throw new Error(
9537
+ 'Python proxy dev server requires "config.handlerFunction" to be set'
9538
+ );
9539
+ }
9540
+ const serverKey = `${workPath}::proxy::${entrypoint}`;
9541
+ const existing = await getPersistentServer(serverKey);
9542
+ if (existing) {
9543
+ return existing;
9544
+ }
9545
+ if (!restoreWarnings)
9546
+ restoreWarnings = silenceNodeWarnings();
9547
+ 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
+ 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
+ try {
9566
+ const { pythonPath: systemPython } = getDefaultPythonVersion(meta);
9567
+ const uvPath = await findUvBinary(systemPython);
9568
+ if (uvPath) {
9569
+ checkUvBinaryVersion(uvPath);
9570
+ }
9571
+ const venvPath = (0, import_path13.join)(
9572
+ workPath,
9573
+ ".vercel",
9574
+ "python",
9575
+ PROXY_DEPENDENCY_GROUP,
9576
+ ".venv"
9577
+ );
9578
+ await ensureVenv({
9579
+ pythonVersion: { pythonPath: systemPython },
9580
+ venvPath,
9581
+ uvPath,
9582
+ quiet: true
9583
+ });
9584
+ const pythonCmd = getVenvPythonBin(venvPath);
9585
+ env.VIRTUAL_ENV = venvPath;
9586
+ env.PATH = `${getVenvBinDir(venvPath)}${import_path13.delimiter}${env.PATH || ""}`;
9587
+ await syncDependencies({
9588
+ workPath,
9589
+ uvPath,
9590
+ pythonBin: pythonCmd,
9591
+ env,
9592
+ onStdout,
9593
+ onStderr,
9594
+ onlyGroup: PROXY_DEPENDENCY_GROUP,
9595
+ activeVenv: true
9596
+ });
9597
+ await installInjectedDevPackage(
9598
+ {
9599
+ name: "vercel-runtime",
9600
+ pinnedVersion: VERCEL_RUNTIME_VERSION,
9601
+ envOverride: env.VERCEL_RUNTIME_PYTHON
9602
+ },
9603
+ { workPath, uvPath, pythonBin: pythonCmd, env, onStdout, onStderr }
9604
+ );
9605
+ const { port, pid } = await spawnPersistentServer({
9606
+ serverKey,
9607
+ workPath,
9608
+ entry: entrypoint,
9609
+ modulePath: entrypointToModule(entrypoint),
9610
+ shimSubdir: PROXY_DEPENDENCY_GROUP,
9611
+ framework: "python",
9612
+ variableName: handlerFunction,
9613
+ spawnCommand: pythonCmd,
9614
+ spawnArgsPrefix: [],
9615
+ env,
9616
+ onStdout,
9617
+ onStderr
9618
+ });
9619
+ resolveChildReady({ port, pid });
9620
+ return { port, pid, shutdown: async () => {
9621
+ } };
9622
+ } catch (err) {
9623
+ rejectChildReady(err);
9624
+ throw err;
9625
+ } finally {
9626
+ PENDING_STARTS.delete(serverKey);
9627
+ }
9628
+ };
9367
9629
  var startDevServer = async (opts) => {
9630
+ if (opts.config?.middleware === true) {
9631
+ return startProxyDevServer(opts);
9632
+ }
9368
9633
  const {
9369
9634
  entrypoint: rawEntrypoint,
9370
9635
  workPath,
@@ -9382,24 +9647,12 @@ var startDevServer = async (opts) => {
9382
9647
  const scheduleEnv = scheduleFunction ? { ...env } : void 0;
9383
9648
  const serviceName = service?.name ?? (typeof meta.serviceName === "string" ? meta.serviceName : void 0);
9384
9649
  const serverKey = scheduleFunction ? `${workPath}::schedule::${scheduleFunction.outputPath}` : serviceName ? `${workPath}::${framework}::${serviceName}` : `${workPath}::${framework}`;
9385
- while (true) {
9386
- const existing = PERSISTENT_SERVERS.get(serverKey);
9387
- if (existing) {
9388
- if (scheduleFunction && (existing.scheduleModule !== scheduleModule || !(0, import_util2.isDeepStrictEqual)(existing.scheduleEnv, scheduleEnv))) {
9389
- killPersistentServer(serverKey);
9390
- } else {
9391
- return {
9392
- port: existing.port,
9393
- pid: existing.pid,
9394
- shutdown: async () => {
9395
- }
9396
- };
9397
- }
9398
- }
9399
- const pending = PENDING_STARTS.get(serverKey);
9400
- if (!pending)
9401
- break;
9402
- await pending;
9650
+ const existing = await getPersistentServer(
9651
+ serverKey,
9652
+ (info) => !!scheduleFunction && (info.scheduleModule !== scheduleModule || !(0, import_util2.isDeepStrictEqual)(info.scheduleEnv, scheduleEnv))
9653
+ );
9654
+ if (existing) {
9655
+ return existing;
9403
9656
  }
9404
9657
  if (!framework && !scheduleFunction) {
9405
9658
  return null;
@@ -9461,9 +9714,6 @@ var startDevServer = async (opts) => {
9461
9714
  }
9462
9715
  const { entrypoint: entry, variableName } = resolved;
9463
9716
  const modulePath = scheduleHandlerPath ? generatedPythonPathToModule(scheduleHandlerPath) : entrypointToModule(entry);
9464
- let childProcess = null;
9465
- let stdoutLogListener = null;
9466
- let stderrLogListener = null;
9467
9717
  let resolveChildReady;
9468
9718
  let rejectChildReady;
9469
9719
  const childReady = new Promise(
@@ -9713,82 +9963,25 @@ If you are using a virtual environment, activate it before running "vercel dev",
9713
9963
  if (crons?.length) {
9714
9964
  env.__VC_CRON_ROUTES = JSON.stringify(buildCronRouteTable(crons));
9715
9965
  }
9716
- const port = typeof meta.port === "number" ? meta.port : await (0, import_get_port.default)();
9717
- env.PORT = `${port}`;
9718
- if (entry) {
9719
- env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path13.join)(workPath, entry);
9720
- }
9721
- const devShim = createDevShim(
9966
+ const { port, pid } = await spawnPersistentServer({
9967
+ serverKey,
9722
9968
  workPath,
9723
9969
  entry,
9724
9970
  modulePath,
9725
- scheduleHandlerPath ? scheduleHandlerPath.replace(/\.py$/, "") : serviceName && import_path13.posix.join("services", serviceName),
9726
- framework ?? "python",
9727
- variableName ?? ""
9728
- );
9729
- if (devShim) {
9730
- const shimDir = devShim.shimDir || (0, import_path13.join)(workPath, ".vercel", "python");
9731
- const runtimeDir = (0, import_path13.join)(workPath, ".vercel", "python");
9732
- const pathParts = shimDir !== runtimeDir ? [shimDir, runtimeDir] : [shimDir];
9733
- if (devShim.extraPythonPath) {
9734
- pathParts.push(devShim.extraPythonPath);
9735
- }
9736
- if (hookResult?.extraPythonPath) {
9737
- pathParts.push(hookResult.extraPythonPath);
9738
- }
9739
- const existingPythonPath = env.PYTHONPATH || "";
9740
- if (existingPythonPath) {
9741
- pathParts.push(existingPythonPath);
9742
- }
9743
- env.PYTHONPATH = pathParts.join(import_path13.delimiter);
9744
- }
9745
- const moduleToRun = devShim?.module || modulePath;
9746
- const pythonArgs = ["-u", "-m", moduleToRun];
9747
- const argv = [...spawnArgsPrefix, ...pythonArgs];
9748
- (0, import_build_utils15.debug)(
9749
- `Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
9750
- );
9751
- if (process.stdout.columns) {
9752
- env.COLUMNS = `${process.stdout.columns}`;
9753
- }
9754
- const child = (0, import_child_process2.spawn)(spawnCommand, argv, {
9755
- cwd: workPath,
9971
+ shimSubdir: scheduleHandlerPath ? scheduleHandlerPath.replace(/\.py$/, "") : serviceName && import_path13.posix.join("services", serviceName),
9972
+ framework: framework ?? "python",
9973
+ variableName: variableName ?? "",
9974
+ extraPythonPath: hookResult?.extraPythonPath,
9975
+ spawnCommand,
9976
+ spawnArgsPrefix,
9977
+ port: typeof meta.port === "number" ? meta.port : void 0,
9756
9978
  env,
9757
- stdio: ["ignore", "pipe", "pipe"],
9758
- detached: true
9759
- });
9760
- childProcess = child;
9761
- stdoutLogListener = createLogListener(onStdout, process.stdout);
9762
- stderrLogListener = createLogListener(onStderr, process.stderr);
9763
- child.stdout?.on("data", stdoutLogListener);
9764
- child.stderr?.on("data", stderrLogListener);
9765
- const childExited = new Promise((_resolve, reject) => {
9766
- child.once("error", (err) => {
9767
- reject(err);
9768
- });
9769
- child.once("exit", (code, signal) => {
9770
- reject(
9771
- new Error(
9772
- `Python dev server exited before binding (code=${code}, signal=${signal})`
9773
- )
9774
- );
9775
- });
9776
- });
9777
- await Promise.race([
9778
- checkForPort(port, DEV_SERVER_STARTUP_TIMEOUT),
9779
- childExited
9780
- ]);
9781
- const pid = child.pid;
9782
- resolveChildReady({ port, pid });
9783
- PERSISTENT_SERVERS.set(serverKey, {
9784
- port,
9785
- pid,
9786
- child: childProcess,
9787
- stdoutLogListener,
9788
- stderrLogListener,
9979
+ onStdout,
9980
+ onStderr,
9789
9981
  scheduleModule,
9790
9982
  scheduleEnv
9791
9983
  });
9984
+ resolveChildReady({ port, pid });
9792
9985
  const shutdown = async () => {
9793
9986
  };
9794
9987
  return { port, pid, shutdown, crons, queueSubscriptions };
@@ -9802,7 +9995,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
9802
9995
 
9803
9996
  // src/quirks/index.ts
9804
9997
  var import_build_utils18 = require("@vercel/build-utils");
9805
- var import_python_analysis10 = require("@vercel/python-analysis");
9998
+ var import_python_analysis11 = require("@vercel/python-analysis");
9806
9999
 
9807
10000
  // src/quirks/matplotlib.ts
9808
10001
  var matplotlibQuirk = {
@@ -9882,7 +10075,7 @@ var import_fs15 = __toESM(require("fs"));
9882
10075
  var import_path15 = require("path");
9883
10076
  var import_execa7 = __toESM(require_execa());
9884
10077
  var import_build_utils17 = require("@vercel/build-utils");
9885
- var import_python_analysis9 = require("@vercel/python-analysis");
10078
+ var import_python_analysis10 = require("@vercel/python-analysis");
9886
10079
  function execErrorMessage(err) {
9887
10080
  if (err != null && typeof err === "object" && "stderr" in err) {
9888
10081
  const stderr = String(err.stderr);
@@ -10142,7 +10335,7 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
10142
10335
  (0, import_path15.join)(sitePackages, "prisma"),
10143
10336
  sitePackages
10144
10337
  );
10145
- const count = await (0, import_python_analysis9.extendDistRecord)(sitePackages, "prisma", allFiles);
10338
+ const count = await (0, import_python_analysis10.extendDistRecord)(sitePackages, "prisma", allFiles);
10146
10339
  if (count > 0) {
10147
10340
  (0, import_build_utils17.debug)(`Appended ${count} entries to prisma RECORD`);
10148
10341
  }
@@ -10167,7 +10360,7 @@ var quirks = [litellmQuirk, prismaQuirk, matplotlibQuirk];
10167
10360
  function toposortQuirks(activated) {
10168
10361
  const nameToQuirk = /* @__PURE__ */ new Map();
10169
10362
  for (const q of activated) {
10170
- nameToQuirk.set((0, import_python_analysis10.normalizePackageName)(q.dependency), q);
10363
+ nameToQuirk.set((0, import_python_analysis11.normalizePackageName)(q.dependency), q);
10171
10364
  }
10172
10365
  const adj = /* @__PURE__ */ new Map();
10173
10366
  const inDegree = /* @__PURE__ */ new Map();
@@ -10178,7 +10371,7 @@ function toposortQuirks(activated) {
10178
10371
  for (const q of activated) {
10179
10372
  if (q.runsBefore) {
10180
10373
  for (const dep of q.runsBefore) {
10181
- const target = nameToQuirk.get((0, import_python_analysis10.normalizePackageName)(dep));
10374
+ const target = nameToQuirk.get((0, import_python_analysis11.normalizePackageName)(dep));
10182
10375
  if (target) {
10183
10376
  adj.get(q).add(target);
10184
10377
  inDegree.set(target, inDegree.get(target) + 1);
@@ -10187,7 +10380,7 @@ function toposortQuirks(activated) {
10187
10380
  }
10188
10381
  if (q.runsAfter) {
10189
10382
  for (const dep of q.runsAfter) {
10190
- const source = nameToQuirk.get((0, import_python_analysis10.normalizePackageName)(dep));
10383
+ const source = nameToQuirk.get((0, import_python_analysis11.normalizePackageName)(dep));
10191
10384
  if (source) {
10192
10385
  adj.get(source).add(q);
10193
10386
  inDegree.set(q, inDegree.get(q) + 1);
@@ -10228,14 +10421,14 @@ async function runQuirks(ctx) {
10228
10421
  const installedNames = /* @__PURE__ */ new Set();
10229
10422
  const sitePackageDirs = await getVenvSitePackagesDirs(ctx.venvPath);
10230
10423
  for (const dir of sitePackageDirs) {
10231
- const distributions = await (0, import_python_analysis10.scanDistributions)(dir);
10424
+ const distributions = await (0, import_python_analysis11.scanDistributions)(dir);
10232
10425
  for (const name of distributions.keys()) {
10233
- installedNames.add((0, import_python_analysis10.normalizePackageName)(name));
10426
+ installedNames.add((0, import_python_analysis11.normalizePackageName)(name));
10234
10427
  }
10235
10428
  }
10236
10429
  const activated = quirks.filter((quirk) => {
10237
10430
  const installed = installedNames.has(
10238
- (0, import_python_analysis10.normalizePackageName)(quirk.dependency)
10431
+ (0, import_python_analysis11.normalizePackageName)(quirk.dependency)
10239
10432
  );
10240
10433
  if (!installed) {
10241
10434
  (0, import_build_utils18.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
@@ -10449,7 +10642,7 @@ function fastapiStaticOptions(installedDistributions) {
10449
10642
  }
10450
10643
 
10451
10644
  // src/index.ts
10452
- var import_python_analysis12 = require("@vercel/python-analysis");
10645
+ var import_python_analysis13 = require("@vercel/python-analysis");
10453
10646
 
10454
10647
  // src/bytecode-packing.ts
10455
10648
  function isBytecodeAnalysisDisabled() {
@@ -10749,7 +10942,7 @@ async function collectAppBytecodeFiles({
10749
10942
  var import_fs19 = __toESM(require("fs"));
10750
10943
  var import_path19 = require("path");
10751
10944
  var import_build_utils22 = require("@vercel/build-utils");
10752
- var import_python_analysis11 = require("@vercel/python-analysis");
10945
+ var import_python_analysis12 = require("@vercel/python-analysis");
10753
10946
  var STRIP_BASENAMES = /* @__PURE__ */ new Set([
10754
10947
  "py.typed",
10755
10948
  "WHEEL",
@@ -10775,7 +10968,7 @@ function getDistributionFileGroups({
10775
10968
  if (includePackages?.length === 0) {
10776
10969
  return [];
10777
10970
  }
10778
- const includeSet = includePackages ? new Set(includePackages.map(import_python_analysis11.normalizePackageName)) : null;
10971
+ const includeSet = includePackages ? new Set(includePackages.map(import_python_analysis12.normalizePackageName)) : null;
10779
10972
  const groups = [];
10780
10973
  for (const dir of sitePackageDirs) {
10781
10974
  const dirDistributions = distributions.get(dir);
@@ -10783,7 +10976,7 @@ function getDistributionFileGroups({
10783
10976
  continue;
10784
10977
  const sitePackagesDir = (0, import_path19.resolve)(dir);
10785
10978
  for (const [name, distribution] of dirDistributions) {
10786
- const packageName = (0, import_python_analysis11.normalizePackageName)(name);
10979
+ const packageName = (0, import_python_analysis12.normalizePackageName)(name);
10787
10980
  if (includeSet && !includeSet.has(packageName))
10788
10981
  continue;
10789
10982
  const files = [];
@@ -10803,11 +10996,28 @@ function getDistributionFileGroups({
10803
10996
  }
10804
10997
  return groups;
10805
10998
  }
10999
+ function withoutPackages(distributions, packageNames) {
11000
+ if (packageNames.length === 0) {
11001
+ return distributions;
11002
+ }
11003
+ const excluded = new Set(packageNames.map(import_python_analysis12.normalizePackageName));
11004
+ const filtered = /* @__PURE__ */ new Map();
11005
+ for (const [dir, index] of distributions) {
11006
+ filtered.set(
11007
+ dir,
11008
+ new Map(
11009
+ [...index].filter(([name]) => !excluded.has((0, import_python_analysis12.normalizePackageName)(name)))
11010
+ )
11011
+ );
11012
+ }
11013
+ return filtered;
11014
+ }
10806
11015
  var InstalledPythonDistributions = class _InstalledPythonDistributions {
10807
11016
  static async load({
10808
11017
  venvPath,
10809
11018
  pythonMajor,
10810
- pythonMinor
11019
+ pythonMinor,
11020
+ excludePackages
10811
11021
  }) {
10812
11022
  const sitePackageDirs = await getVenvSitePackagesDirs(venvPath);
10813
11023
  const distributions = /* @__PURE__ */ new Map();
@@ -10817,18 +11027,22 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
10817
11027
  } catch {
10818
11028
  continue;
10819
11029
  }
10820
- distributions.set(dir, await (0, import_python_analysis11.scanDistributions)(dir));
11030
+ distributions.set(dir, await (0, import_python_analysis12.scanDistributions)(dir));
10821
11031
  }
10822
11032
  return new _InstalledPythonDistributions({
10823
11033
  sitePackageDirs,
10824
11034
  distributions,
10825
11035
  pythonMajor,
10826
- pythonMinor
11036
+ pythonMinor,
11037
+ excludePackages
10827
11038
  });
10828
11039
  }
10829
11040
  constructor(options) {
10830
11041
  this.sitePackageDirs = options.sitePackageDirs;
10831
- this.distributions = options.distributions;
11042
+ this.distributions = withoutPackages(
11043
+ options.distributions,
11044
+ options.excludePackages ?? []
11045
+ );
10832
11046
  this.pythonMajor = options.pythonMajor;
10833
11047
  this.pythonMinor = options.pythonMinor;
10834
11048
  }
@@ -10844,7 +11058,7 @@ var InstalledPythonDistributions = class _InstalledPythonDistributions {
10844
11058
  * normalization), or null when the package is not found in the venv.
10845
11059
  */
10846
11060
  getInstalledVersion(packageName) {
10847
- const target = (0, import_python_analysis11.normalizePackageName)(packageName);
11061
+ const target = (0, import_python_analysis12.normalizePackageName)(packageName);
10848
11062
  for (const index of this.distributions.values()) {
10849
11063
  const dist = index.get(target);
10850
11064
  if (dist)
@@ -11691,7 +11905,10 @@ async function packFunctionBundle({
11691
11905
  const installedDistributions2 = await InstalledPythonDistributions.load({
11692
11906
  venvPath,
11693
11907
  pythonMajor: pythonVersion.major,
11694
- pythonMinor: pythonVersion.minor
11908
+ pythonMinor: pythonVersion.minor,
11909
+ // Without a uv.lock (custom install commands), a seeded package may
11910
+ // be one the project installed on purpose, so it stays bundled.
11911
+ excludePackages: uvLockPath ? await getSeedPackagesMissingFromLock(uvLockPath) : []
11695
11912
  });
11696
11913
  const depExternalizer = new PythonDependencyExternalizer({
11697
11914
  installedDistributions: installedDistributions2,
@@ -11752,7 +11969,7 @@ async function packFunctionBundle({
11752
11969
  try {
11753
11970
  const sitePackageDirs = installedDistributions2.getSitePackageDirs();
11754
11971
  const closure = await withTimeout(
11755
- (0, import_python_analysis12.collectImportClosure)(
11972
+ (0, import_python_analysis13.collectImportClosure)(
11756
11973
  getImportClosureOptions({
11757
11974
  workPath,
11758
11975
  entrypoint,
@@ -12018,7 +12235,7 @@ async function buildProxyMiddleware({
12018
12235
  (0, import_path21.join)(workPath, entrypoint),
12019
12236
  "utf-8"
12020
12237
  );
12021
- if (!await (0, import_python_analysis12.containsTopLevelCallable)(proxySource, proxyHandlerFunction)) {
12238
+ if (!await (0, import_python_analysis13.containsTopLevelCallable)(proxySource, proxyHandlerFunction)) {
12022
12239
  throw new import_build_utils24.NowBuildError({
12023
12240
  code: "PYTHON_HANDLER_NOT_FOUND",
12024
12241
  message: `Handler function "${proxyHandlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
@@ -12051,7 +12268,9 @@ async function buildProxyMiddleware({
12051
12268
  // Install only the proxy's dependency group into the proxy venv;
12052
12269
  // the project itself is neither built nor installed.
12053
12270
  // If the group is absent the proxy has no extra deps — skip sync.
12054
- extraSyncParams: "vercel.proxy" in (pythonPackage?.manifest?.data?.["dependency-groups"] ?? {}) ? { onlyGroup: "vercel.proxy", noInstallProject: true } : void 0
12271
+ // Group names are normalized on read, so `vercel.proxy` is keyed
12272
+ // as `vercel-proxy`.
12273
+ extraSyncParams: "vercel-proxy" in (pythonPackage?.manifest?.data?.["dependency-groups"] ?? {}) ? { onlyGroup: "vercel.proxy", noInstallProject: true } : void 0
12055
12274
  })
12056
12275
  );
12057
12276
  const pipPlatformArgs = target.uvPlatform ? ["--python-platform", target.uvPlatform] : [];
@@ -12592,7 +12811,7 @@ var build = async ({
12592
12811
  if (handlerFunction) {
12593
12812
  const entrypointPath = (0, import_path21.join)(workPath, entrypoint);
12594
12813
  const source = await import_fs20.default.promises.readFile(entrypointPath, "utf-8");
12595
- const found = await (0, import_python_analysis12.containsTopLevelCallable)(source, handlerFunction);
12814
+ const found = await (0, import_python_analysis13.containsTopLevelCallable)(source, handlerFunction);
12596
12815
  if (!found) {
12597
12816
  throw new import_build_utils24.NowBuildError({
12598
12817
  code: "PYTHON_HANDLER_NOT_FOUND",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "25.0.0",
3
+ "version": "25.1.2",
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.14.0"
17
+ "@vercel/python-analysis": "0.15.0"
18
18
  },
19
19
  "peerDependencies": {
20
- "@vercel/build-utils": "14.21.0"
20
+ "@vercel/build-utils": "14.21.2"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@renovatebot/pep440": "4.2.1",
@@ -37,9 +37,9 @@
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.0",
40
+ "@vercel/build-utils": "14.21.2",
41
41
  "@vercel/error-utils": "2.2.1",
42
- "@vercel/python-runtime": "0.23.2"
42
+ "@vercel/python-runtime": "0.23.3"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "node ../../utils/build-builder.mjs",