@vercel/python 6.20.0 → 6.20.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 +328 -449
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -989,10 +989,10 @@ var require_semver = __commonJS({
989
989
  var rangeTmp;
990
990
  if (this.operator === "") {
991
991
  rangeTmp = new Range(comp.value, options);
992
- return satisfies2(this.value, rangeTmp, options);
992
+ return satisfies(this.value, rangeTmp, options);
993
993
  } else if (comp.operator === "") {
994
994
  rangeTmp = new Range(this.value, options);
995
- return satisfies2(comp.semver, rangeTmp, options);
995
+ return satisfies(comp.semver, rangeTmp, options);
996
996
  }
997
997
  var sameDirectionIncreasing = (this.operator === ">=" || this.operator === ">") && (comp.operator === ">=" || comp.operator === ">");
998
998
  var sameDirectionDecreasing = (this.operator === "<=" || this.operator === "<") && (comp.operator === "<=" || comp.operator === "<");
@@ -1301,8 +1301,8 @@ var require_semver = __commonJS({
1301
1301
  }
1302
1302
  return true;
1303
1303
  }
1304
- exports.satisfies = satisfies2;
1305
- function satisfies2(version2, range, options) {
1304
+ exports.satisfies = satisfies;
1305
+ function satisfies(version2, range, options) {
1306
1306
  try {
1307
1307
  range = new Range(range, options);
1308
1308
  } catch (er) {
@@ -1430,7 +1430,7 @@ var require_semver = __commonJS({
1430
1430
  default:
1431
1431
  throw new TypeError('Must provide a hilo val of "<" or ">"');
1432
1432
  }
1433
- if (satisfies2(version2, range, options)) {
1433
+ if (satisfies(version2, range, options)) {
1434
1434
  return false;
1435
1435
  }
1436
1436
  for (var i2 = 0; i2 < range.set.length; ++i2) {
@@ -2651,7 +2651,7 @@ ${stderr}${stdout}`;
2651
2651
  var require_lib = __commonJS({
2652
2652
  "../../node_modules/.pnpm/which@3.0.0/node_modules/which/lib/index.js"(exports, module2) {
2653
2653
  var isexe = require_isexe();
2654
- var { join: join10, delimiter: delimiter2, sep: sep2, posix } = require("path");
2654
+ var { join: join11, delimiter: delimiter2, sep: sep2, posix } = require("path");
2655
2655
  var isWindows = process.platform === "win32";
2656
2656
  var rSlash = new RegExp(`[${posix.sep}${sep2 === posix.sep ? "" : sep2}]`.replace(/(\\)/g, "\\$1"));
2657
2657
  var rRel = new RegExp(`^\\.${rSlash.source}`);
@@ -2680,7 +2680,7 @@ var require_lib = __commonJS({
2680
2680
  var getPathPart = (raw, cmd) => {
2681
2681
  const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
2682
2682
  const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
2683
- return prefix + join10(pathPart, cmd);
2683
+ return prefix + join11(pathPart, cmd);
2684
2684
  };
2685
2685
  var which2 = async (cmd, opt = {}) => {
2686
2686
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -2868,11 +2868,11 @@ __export(src_exports, {
2868
2868
  });
2869
2869
  module.exports = __toCommonJS(src_exports);
2870
2870
  var import_fs8 = __toESM(require("fs"));
2871
- var import_util2 = require("util");
2872
- var import_path10 = require("path");
2871
+ var import_path11 = require("path");
2873
2872
 
2874
2873
  // src/package-versions.ts
2875
- var VERCEL_RUNTIME_VERSION = "0.5.4";
2874
+ var VERCEL_RUNTIME_VERSION = "0.5.6";
2875
+ var VERCEL_WORKERS_VERSION = "0.0.12";
2876
2876
 
2877
2877
  // src/index.ts
2878
2878
  var import_build_utils12 = require("@vercel/build-utils");
@@ -2880,9 +2880,9 @@ var import_build_utils12 = require("@vercel/build-utils");
2880
2880
  // src/install.ts
2881
2881
  var import_execa3 = __toESM(require_execa());
2882
2882
  var import_fs3 = __toESM(require("fs"));
2883
- var import_path4 = require("path");
2883
+ var import_path5 = require("path");
2884
2884
  var import_build_utils4 = require("@vercel/build-utils");
2885
- var import_python_analysis = require("@vercel/python-analysis");
2885
+ var import_python_analysis2 = require("@vercel/python-analysis");
2886
2886
 
2887
2887
  // src/utils.ts
2888
2888
  var import_fs2 = __toESM(require("fs"));
@@ -3268,72 +3268,41 @@ async function runPyprojectScript(workPath, scriptNames, env, useUserVirtualEnv
3268
3268
  }
3269
3269
  return false;
3270
3270
  }
3271
- function findDir({
3272
- file,
3273
- entryDirectory,
3274
- workPath,
3275
- fsFiles
3276
- }) {
3277
- if (fsFiles[(0, import_path3.join)(entryDirectory, file)]) {
3278
- return (0, import_path3.join)(workPath, entryDirectory);
3279
- }
3280
- if (fsFiles[file]) {
3281
- return workPath;
3282
- }
3283
- return null;
3284
- }
3285
3271
 
3286
3272
  // src/version.ts
3273
+ var import_path4 = require("path");
3287
3274
  var import_build_utils3 = require("@vercel/build-utils");
3288
- var DEFAULT_PYTHON_VERSION = "3.12";
3275
+ var import_python_analysis = require("@vercel/python-analysis");
3276
+ function pythonVersionString(pv) {
3277
+ return `${pv.major}.${pv.minor}`;
3278
+ }
3279
+ var DEFAULT_PYTHON_VERSION = makePythonVersion(3, 12);
3280
+ var DEFAULT_PYTHON_VERSION_STRING = pythonVersionString(
3281
+ DEFAULT_PYTHON_VERSION
3282
+ );
3283
+ function makePythonVersion(major, minor, discontinueDate) {
3284
+ return {
3285
+ major,
3286
+ minor,
3287
+ pipPath: `pip${major}.${minor}`,
3288
+ pythonPath: `python${major}.${minor}`,
3289
+ runtime: `python${major}.${minor}`,
3290
+ discontinueDate
3291
+ };
3292
+ }
3289
3293
  var allOptions = [
3290
- {
3291
- version: "3.14",
3292
- pipPath: "pip3.14",
3293
- pythonPath: "python3.14",
3294
- runtime: "python3.14"
3295
- },
3296
- {
3297
- version: "3.13",
3298
- pipPath: "pip3.13",
3299
- pythonPath: "python3.13",
3300
- runtime: "python3.13"
3301
- },
3302
- {
3303
- version: "3.12",
3304
- pipPath: "pip3.12",
3305
- pythonPath: "python3.12",
3306
- runtime: "python3.12"
3307
- },
3308
- {
3309
- version: "3.11",
3310
- pipPath: "pip3.11",
3311
- pythonPath: "python3.11",
3312
- runtime: "python3.11"
3313
- },
3314
- {
3315
- version: "3.10",
3316
- pipPath: "pip3.10",
3317
- pythonPath: "python3.10",
3318
- runtime: "python3.10"
3319
- },
3320
- {
3321
- version: "3.9",
3322
- pipPath: "pip3.9",
3323
- pythonPath: "python3.9",
3324
- runtime: "python3.9"
3325
- },
3326
- {
3327
- version: "3.6",
3328
- pipPath: "pip3.6",
3329
- pythonPath: "python3.6",
3330
- runtime: "python3.6",
3331
- discontinueDate: /* @__PURE__ */ new Date("2022-07-18")
3332
- }
3294
+ makePythonVersion(3, 14),
3295
+ makePythonVersion(3, 13),
3296
+ makePythonVersion(3, 12),
3297
+ makePythonVersion(3, 11),
3298
+ makePythonVersion(3, 10),
3299
+ makePythonVersion(3, 9),
3300
+ makePythonVersion(3, 6, /* @__PURE__ */ new Date("2022-07-18"))
3333
3301
  ];
3334
3302
  function getDevPythonVersion() {
3335
3303
  return {
3336
- version: "3",
3304
+ major: 3,
3305
+ minor: 0,
3337
3306
  pipPath: "pip3",
3338
3307
  pythonPath: "python3",
3339
3308
  runtime: "python3"
@@ -3346,7 +3315,7 @@ function getDefaultPythonVersion({
3346
3315
  return getDevPythonVersion();
3347
3316
  }
3348
3317
  const defaultOption = allOptions.find(
3349
- (opt) => opt.version === DEFAULT_PYTHON_VERSION && isInstalled(opt)
3318
+ (opt) => versionsEqual(opt, DEFAULT_PYTHON_VERSION) && isInstalled(opt)
3350
3319
  );
3351
3320
  if (defaultOption) {
3352
3321
  return defaultOption;
@@ -3361,148 +3330,143 @@ function getDefaultPythonVersion({
3361
3330
  }
3362
3331
  return selection;
3363
3332
  }
3364
- function parseVersionTuple(input) {
3365
- const cleaned = input.trim().replace(/\s+/g, "");
3366
- const m = cleaned.match(/^(\d+)(?:\.(\d+))?/);
3367
- if (!m)
3368
- return null;
3369
- const major = Number(m[1]);
3370
- const minor = m[2] !== void 0 ? Number(m[2]) : 0;
3371
- if (Number.isNaN(major) || Number.isNaN(minor))
3372
- return null;
3373
- return [major, minor];
3333
+ function versionsEqual(a, b) {
3334
+ return a.major === b.major && a.minor === b.minor;
3374
3335
  }
3375
- function compareTuples(a, b) {
3376
- if (a[0] !== b[0])
3377
- return a[0] - b[0];
3378
- return a[1] - b[1];
3336
+ function versionLessOrEqual(a, b) {
3337
+ if (a.major !== b.major)
3338
+ return a.major < b.major;
3339
+ return a.minor <= b.minor;
3379
3340
  }
3380
- function parseSpecifier(spec) {
3381
- const s = spec.trim();
3382
- const m = s.match(
3383
- /^(<=|>=|==|!=|~=|<|>)\s*([0-9]+(?:\.[0-9]+)?)(?:\.[0-9]+)?(?:\.\*)?$/
3384
- ) || // Bare version like "3.11" or "3.11.4" -> implied ==
3385
- s.match(/^()([0-9]+(?:\.[0-9]+)?)(?:\.[0-9]+)?(?:\.\*)?$/);
3386
- if (!m)
3387
- return null;
3388
- const op = m[1] || "==";
3389
- const vt = parseVersionTuple(m[2]);
3390
- if (!vt)
3391
- return null;
3392
- return { op, ver: vt };
3341
+ function toPythonBuild(opt) {
3342
+ return {
3343
+ version: { major: opt.major, minor: opt.minor },
3344
+ implementation: "cpython",
3345
+ variant: "default",
3346
+ os: "linux",
3347
+ architecture: "x86_64",
3348
+ libc: "gnu"
3349
+ };
3393
3350
  }
3394
- function satisfies(candidate, spec) {
3395
- const cmp = compareTuples(candidate, spec.ver);
3396
- switch (spec.op) {
3397
- case "==":
3398
- return cmp === 0;
3399
- case "!=":
3400
- return cmp !== 0;
3401
- case "<":
3402
- return cmp < 0;
3403
- case "<=":
3404
- return cmp <= 0;
3405
- case ">":
3406
- return cmp > 0;
3407
- case ">=":
3408
- return cmp >= 0;
3409
- case "~=": {
3410
- const lowerOk = cmp >= 0;
3411
- const upper = [spec.ver[0], spec.ver[1] + 1];
3412
- return lowerOk && compareTuples(candidate, upper) < 0;
3413
- }
3414
- default:
3415
- return false;
3416
- }
3351
+ function getAvailablePythonBuilds() {
3352
+ const installed = allOptions.filter(
3353
+ (opt) => !isDiscontinued(opt) && isInstalled(opt)
3354
+ );
3355
+ const defaultOpt = installed.find(
3356
+ (opt) => versionsEqual(opt, DEFAULT_PYTHON_VERSION)
3357
+ );
3358
+ const rest = installed.filter(
3359
+ (opt) => !versionsEqual(opt, DEFAULT_PYTHON_VERSION)
3360
+ );
3361
+ const ordered = defaultOpt ? [defaultOpt, ...rest] : rest;
3362
+ return ordered.map(toPythonBuild);
3417
3363
  }
3418
- function selectFromRequiresPython(expr) {
3419
- const raw = expr.trim();
3420
- if (!raw)
3421
- return void 0;
3422
- const parts = raw.split(",").map((p) => p.trim()).filter(Boolean);
3423
- const specifiers = [];
3424
- for (const p of parts) {
3425
- const sp = parseSpecifier(p);
3426
- if (sp)
3427
- specifiers.push(sp);
3428
- }
3429
- if (specifiers.length === 0) {
3430
- return allOptions.find((o) => o.version === raw);
3431
- }
3432
- const matches = allOptions.filter((opt) => {
3433
- const vt = parseVersionTuple(opt.version);
3434
- return specifiers.every((sp) => satisfies(vt, sp));
3435
- });
3436
- if (matches.length === 0)
3437
- return void 0;
3438
- const defaultMatch = matches.find(
3439
- (opt) => opt.version === DEFAULT_PYTHON_VERSION && isInstalled(opt)
3364
+ function getAllPythonBuilds() {
3365
+ return allOptions.map(toPythonBuild);
3366
+ }
3367
+ function getPythonVersionForBuild(build2) {
3368
+ return allOptions.find(
3369
+ (opt) => opt.major === build2.version.major && opt.minor === build2.version.minor
3440
3370
  );
3441
- if (defaultMatch) {
3442
- return defaultMatch;
3443
- }
3444
- const installedMatch = matches.find(isInstalled);
3445
- return installedMatch ?? matches[0];
3446
3371
  }
3447
- function getSupportedPythonVersion({
3372
+ function resolvePythonVersion({
3448
3373
  isDev,
3449
- declaredPythonVersion
3374
+ pythonPackage,
3375
+ rootDir
3450
3376
  }) {
3451
3377
  if (isDev) {
3452
- return getDevPythonVersion();
3378
+ return {
3379
+ pythonVersion: getDevPythonVersion(),
3380
+ pythonPackage
3381
+ };
3453
3382
  }
3454
- let selection = getDefaultPythonVersion({ isDev: false });
3455
- if (declaredPythonVersion) {
3456
- const { version: version2, source } = declaredPythonVersion;
3457
- let requested;
3458
- if (source === "pyproject.toml" || source === ".python-version") {
3459
- requested = selectFromRequiresPython(version2);
3460
- } else {
3461
- requested = allOptions.find((o) => o.version === version2);
3462
- }
3463
- if (requested) {
3464
- if (isDiscontinued(requested)) {
3383
+ const constraints = pythonPackage.requiresPython;
3384
+ const defaultPv = getDefaultPythonVersion({ isDev: false });
3385
+ let selection;
3386
+ let source;
3387
+ let autoUpgraded = false;
3388
+ if (!constraints || constraints.length === 0) {
3389
+ console.log(
3390
+ `No Python version specified in .python-version, pyproject.toml, or Pipfile.lock. Using python version: ${pythonVersionString(defaultPv)}`
3391
+ );
3392
+ selection = defaultPv;
3393
+ } else {
3394
+ const defaultBuild = toPythonBuild(defaultPv);
3395
+ const availableBuilds = getAvailablePythonBuilds();
3396
+ const allBuilds = getAllPythonBuilds();
3397
+ const result = (0, import_python_analysis.selectPythonVersion)({
3398
+ constraints,
3399
+ availableBuilds,
3400
+ allBuilds,
3401
+ defaultBuild,
3402
+ majorMinorOnly: true,
3403
+ legacyTildeEquals: true
3404
+ });
3405
+ source = result.source;
3406
+ selection = getPythonVersionForBuild(result.build) ?? defaultPv;
3407
+ if (pythonPackage.manifest?.origin && !result.notAvailable && !result.invalidConstraint && !versionLessOrEqual(defaultPv, selection)) {
3408
+ const originalVersion = pythonVersionString(selection);
3409
+ selection = defaultPv;
3410
+ autoUpgraded = true;
3411
+ console.log(
3412
+ `Python version ${originalVersion} detected in ${source} is below the minimum supported version. Using python version: ${pythonVersionString(selection)}`
3413
+ );
3414
+ } else if (result.notAvailable) {
3415
+ const npv = getPythonVersionForBuild(result.notAvailable.build);
3416
+ if (npv && isDiscontinued(npv)) {
3465
3417
  throw new import_build_utils3.NowBuildError({
3466
3418
  code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
3467
3419
  link: "https://vercel.link/python-version",
3468
- message: `Python version "${requested.version}" detected in ${source} is discontinued and must be upgraded.`
3420
+ message: `Python version "${pythonVersionString(npv)}" detected in ${source} is discontinued and must be upgraded.`
3469
3421
  });
3470
3422
  }
3471
- if (isInstalled(requested)) {
3472
- selection = requested;
3473
- console.log(`Using Python ${selection.version} from ${source}`);
3474
- } else {
3423
+ if (npv) {
3475
3424
  console.warn(
3476
- `Warning: Python version "${version2}" detected in ${source} is not installed and will be ignored. https://vercel.link/python-version`
3425
+ `Warning: Python version "${pythonVersionString(npv)}" detected in ${source} is not installed and will be ignored. https://vercel.link/python-version`
3477
3426
  );
3478
- console.log(`Using python version: ${selection.version}`);
3479
3427
  }
3480
- } else {
3428
+ console.log(`Using python version: ${pythonVersionString(selection)}`);
3429
+ } else if (result.invalidConstraint) {
3481
3430
  console.warn(
3482
- `Warning: Python version "${version2}" detected in ${source} is invalid and will be ignored. https://vercel.link/python-version`
3431
+ `Warning: Python version "${result.invalidConstraint.versionString}" detected in ${source} is invalid and will be ignored. https://vercel.link/python-version`
3432
+ );
3433
+ console.log(`Using python version: ${pythonVersionString(selection)}`);
3434
+ } else {
3435
+ console.log(
3436
+ `Using Python ${pythonVersionString(selection)} from ${source}`
3483
3437
  );
3484
- console.log(`Using python version: ${selection.version}`);
3485
3438
  }
3486
- } else {
3487
- console.log(
3488
- `No Python version specified in .python-version, pyproject.toml, or Pipfile.lock. Using python version: ${selection.version}`
3489
- );
3490
3439
  }
3491
3440
  if (isDiscontinued(selection)) {
3492
3441
  throw new import_build_utils3.NowBuildError({
3493
3442
  code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
3494
3443
  link: "https://vercel.link/python-version",
3495
- message: `Python version "${selection.version}" declared in project configuration is discontinued and must be upgraded.`
3444
+ message: `Python version "${pythonVersionString(selection)}" declared in project configuration is discontinued and must be upgraded.`
3496
3445
  });
3497
3446
  }
3498
3447
  if (selection.discontinueDate) {
3499
3448
  const d = selection.discontinueDate.toISOString().split("T")[0];
3500
- const srcSuffix = declaredPythonVersion ? `detected in ${declaredPythonVersion.source}` : "selected by runtime";
3449
+ const srcSuffix = source ? `detected in ${source}` : "selected by runtime";
3501
3450
  console.warn(
3502
- `Error: Python version "${selection.version}" ${srcSuffix} has reached End-of-Life. Deployments created on or after ${d} will fail to build. https://vercel.link/python-version`
3451
+ `Error: Python version "${pythonVersionString(selection)}" ${srcSuffix} has reached End-of-Life. Deployments created on or after ${d} will fail to build. https://vercel.link/python-version`
3503
3452
  );
3504
3453
  }
3505
- return selection;
3454
+ let pinVersionFilePath;
3455
+ const hasPythonVersionFile = pythonPackage.configs?.some(
3456
+ (configSet) => configSet[import_python_analysis.PythonConfigKind.PythonVersion] !== void 0
3457
+ ) ?? false;
3458
+ if (!hasPythonVersionFile && pythonPackage.manifest && versionLessOrEqual(selection, defaultPv)) {
3459
+ if (autoUpgraded || !pythonPackage.manifest.origin && source?.endsWith("pyproject.toml")) {
3460
+ const manifestDir = (0, import_path4.join)(rootDir, (0, import_path4.dirname)(pythonPackage.manifest.path));
3461
+ pinVersionFilePath = (0, import_path4.join)(manifestDir, ".python-version");
3462
+ }
3463
+ }
3464
+ return {
3465
+ pythonVersion: selection,
3466
+ pythonPackage,
3467
+ versionSource: source,
3468
+ pinVersionFilePath
3469
+ };
3506
3470
  }
3507
3471
  function isDiscontinued({ discontinueDate }) {
3508
3472
  const today = Date.now();
@@ -3525,10 +3489,10 @@ function getInstalledPythons() {
3525
3489
  installedPythonsCache = uv.listInstalledPythons();
3526
3490
  return installedPythonsCache;
3527
3491
  }
3528
- function isInstalled({ version: version2 }) {
3492
+ function isInstalled(pv) {
3529
3493
  try {
3530
3494
  const installed = getInstalledPythons();
3531
- return installed.has(version2);
3495
+ return installed.has(pythonVersionString(pv));
3532
3496
  } catch (err) {
3533
3497
  throw new import_build_utils3.NowBuildError({
3534
3498
  code: "UV_ERROR",
@@ -3553,11 +3517,11 @@ async function isInstalled2(pythonPath, dependency, cwd) {
3553
3517
  {
3554
3518
  stdio: "pipe",
3555
3519
  cwd,
3556
- env: { ...process.env, PYTHONPATH: (0, import_path4.join)(cwd, resolveVendorDir()) }
3520
+ env: { ...process.env, PYTHONPATH: (0, import_path5.join)(cwd, resolveVendorDir()) }
3557
3521
  }
3558
3522
  );
3559
3523
  return stdout.startsWith(cwd);
3560
- } catch (err) {
3524
+ } catch (_err) {
3561
3525
  return false;
3562
3526
  }
3563
3527
  }
@@ -3576,11 +3540,11 @@ async function areRequirementsInstalled(pythonPath, requirementsPath, cwd) {
3576
3540
  {
3577
3541
  stdio: "pipe",
3578
3542
  cwd,
3579
- env: { ...process.env, PYTHONPATH: (0, import_path4.join)(cwd, resolveVendorDir()) }
3543
+ env: { ...process.env, PYTHONPATH: (0, import_path5.join)(cwd, resolveVendorDir()) }
3580
3544
  }
3581
3545
  );
3582
3546
  return true;
3583
- } catch (err) {
3547
+ } catch (_err) {
3584
3548
  return false;
3585
3549
  }
3586
3550
  }
@@ -3614,88 +3578,74 @@ function resolveVendorDir() {
3614
3578
  const vendorDir = process.env.VERCEL_PYTHON_VENDOR_DIR || "_vendor";
3615
3579
  return vendorDir;
3616
3580
  }
3617
- function toBuildError(error) {
3618
- return new import_build_utils4.NowBuildError({
3619
- code: error.code,
3620
- message: error.message,
3621
- link: error.link,
3622
- action: error.action
3623
- });
3624
- }
3625
- async function detectInstallSource({
3626
- workPath,
3627
- entryDirectory,
3628
- repoRootPath
3581
+ async function discoverPackage({
3582
+ entrypointDir,
3583
+ rootDir
3629
3584
  }) {
3630
- const entrypointDir = (0, import_path4.join)(workPath, entryDirectory);
3631
- const rootDir = repoRootPath ?? workPath;
3632
- let pythonPackage;
3633
3585
  try {
3634
- pythonPackage = await (0, import_python_analysis.discoverPythonPackage)({
3635
- entrypointDir,
3636
- rootDir
3637
- });
3586
+ return await (0, import_python_analysis2.discoverPythonPackage)({ entrypointDir, rootDir });
3638
3587
  } catch (error) {
3639
- if (error instanceof import_python_analysis.PythonAnalysisError) {
3588
+ if (error instanceof import_python_analysis2.PythonAnalysisError) {
3640
3589
  if (error.fileContent && (error.code.endsWith("_PARSE_ERROR") || error.code.endsWith("_VALIDATION_ERROR"))) {
3641
3590
  console.log(
3642
3591
  `Failed to parse "${error.path}". File content:
3643
3592
  ${error.fileContent}`
3644
3593
  );
3645
3594
  }
3646
- throw toBuildError(error);
3595
+ throw new import_build_utils4.NowBuildError({
3596
+ code: error.code,
3597
+ message: error.message,
3598
+ link: error.link,
3599
+ action: error.action
3600
+ });
3647
3601
  }
3648
3602
  throw error;
3649
3603
  }
3604
+ }
3605
+ function detectInstallSource(pythonPackage, rootDir) {
3650
3606
  let manifestType = null;
3651
3607
  let manifestPath = null;
3652
3608
  const lockFile = pythonPackage.manifest?.lockFile ?? pythonPackage.workspaceLockFile;
3653
3609
  if (lockFile) {
3654
- if (lockFile.kind === import_python_analysis.PythonLockFileKind.UvLock) {
3610
+ if (lockFile.kind === import_python_analysis2.PythonLockFileKind.UvLock) {
3655
3611
  manifestType = "uv.lock";
3656
- manifestPath = (0, import_path4.join)(rootDir, lockFile.path);
3657
- } else if (lockFile.kind === import_python_analysis.PythonLockFileKind.PylockToml) {
3612
+ manifestPath = (0, import_path5.join)(rootDir, lockFile.path);
3613
+ } else if (lockFile.kind === import_python_analysis2.PythonLockFileKind.PylockToml) {
3658
3614
  manifestType = "pylock.toml";
3659
- manifestPath = (0, import_path4.join)(rootDir, lockFile.path);
3615
+ manifestPath = (0, import_path5.join)(rootDir, lockFile.path);
3660
3616
  }
3661
3617
  } else if (pythonPackage.manifest) {
3662
3618
  manifestType = "pyproject.toml";
3663
- manifestPath = (0, import_path4.join)(rootDir, pythonPackage.manifest.path);
3619
+ manifestPath = (0, import_path5.join)(rootDir, pythonPackage.manifest.path);
3664
3620
  }
3665
3621
  return { manifestPath, manifestType, pythonPackage };
3666
3622
  }
3667
3623
  async function ensureUvProject({
3668
3624
  workPath,
3669
- entryDirectory,
3670
- repoRootPath,
3625
+ rootDir,
3626
+ pythonPackage,
3671
3627
  pythonVersion,
3672
3628
  uv,
3673
3629
  generateLockFile = false,
3674
3630
  requireBinaryWheels = false
3675
3631
  }) {
3676
- const rootDir = repoRootPath ?? workPath;
3677
- const installInfo = await detectInstallSource({
3678
- workPath,
3679
- entryDirectory,
3680
- repoRootPath
3681
- });
3682
- const { manifestType, pythonPackage } = installInfo;
3683
- const manifest = pythonPackage?.manifest;
3632
+ const { manifestType } = detectInstallSource(pythonPackage, rootDir);
3633
+ const manifest = pythonPackage.manifest;
3684
3634
  let projectDir;
3685
3635
  let pyprojectPath;
3686
3636
  let lockPath = null;
3687
3637
  let lockFileProvidedByUser = false;
3688
3638
  if (manifestType === "uv.lock" || manifestType === "pylock.toml") {
3689
3639
  lockFileProvidedByUser = true;
3690
- const lockFile = pythonPackage?.manifest?.lockFile ?? pythonPackage?.workspaceLockFile;
3640
+ const lockFile = pythonPackage.manifest?.lockFile ?? pythonPackage.workspaceLockFile;
3691
3641
  if (!lockFile) {
3692
3642
  throw new Error(
3693
3643
  `Expected lock file path to be resolved, but it was null`
3694
3644
  );
3695
3645
  }
3696
- lockPath = (0, import_path4.join)(rootDir, lockFile.path);
3697
- projectDir = (0, import_path4.dirname)(lockPath);
3698
- pyprojectPath = (0, import_path4.join)(projectDir, "pyproject.toml");
3646
+ lockPath = (0, import_path5.join)(rootDir, lockFile.path);
3647
+ projectDir = (0, import_path5.dirname)(lockPath);
3648
+ pyprojectPath = (0, import_path5.join)(projectDir, "pyproject.toml");
3699
3649
  if (!import_fs3.default.existsSync(pyprojectPath)) {
3700
3650
  throw new Error(
3701
3651
  `Expected "pyproject.toml" next to "${lockFile.kind}" in "${projectDir}"`
@@ -3703,14 +3653,14 @@ async function ensureUvProject({
3703
3653
  }
3704
3654
  console.log(`Installing required dependencies from ${lockFile.kind}...`);
3705
3655
  } else if (manifest) {
3706
- projectDir = (0, import_path4.join)(rootDir, (0, import_path4.dirname)(manifest.path));
3707
- pyprojectPath = (0, import_path4.join)(rootDir, manifest.path);
3656
+ projectDir = (0, import_path5.join)(rootDir, (0, import_path5.dirname)(manifest.path));
3657
+ pyprojectPath = (0, import_path5.join)(rootDir, manifest.path);
3708
3658
  const originKind = manifest.origin?.kind;
3709
- if (originKind === import_python_analysis.PythonManifestConvertedKind.Pipfile) {
3659
+ if (originKind === import_python_analysis2.PythonManifestConvertedKind.Pipfile) {
3710
3660
  console.log("Installing required dependencies from Pipfile...");
3711
- } else if (originKind === import_python_analysis.PythonManifestConvertedKind.PipfileLock) {
3661
+ } else if (originKind === import_python_analysis2.PythonManifestConvertedKind.PipfileLock) {
3712
3662
  console.log("Installing required dependencies from Pipfile.lock...");
3713
- } else if (originKind === import_python_analysis.PythonManifestConvertedKind.RequirementsTxt || originKind === import_python_analysis.PythonManifestConvertedKind.RequirementsIn) {
3663
+ } else if (originKind === import_python_analysis2.PythonManifestConvertedKind.RequirementsTxt || originKind === import_python_analysis2.PythonManifestConvertedKind.RequirementsIn) {
3714
3664
  console.log(
3715
3665
  `Installing required dependencies from ${manifest.origin?.path ?? "requirements.txt"}...`
3716
3666
  );
@@ -3718,16 +3668,16 @@ async function ensureUvProject({
3718
3668
  console.log("Installing required dependencies from pyproject.toml...");
3719
3669
  }
3720
3670
  if (manifest.origin) {
3721
- if (manifest.data.project && !manifest.data.project["requires-python"]) {
3671
+ if (manifest.data.project) {
3722
3672
  manifest.data.project["requires-python"] = `~=${pythonVersion}.0`;
3723
3673
  }
3724
- const content = (0, import_python_analysis.stringifyManifest)(manifest.data);
3725
- pyprojectPath = (0, import_path4.join)(projectDir, "pyproject.toml");
3674
+ const content = (0, import_python_analysis2.stringifyManifest)(manifest.data);
3675
+ pyprojectPath = (0, import_path5.join)(projectDir, "pyproject.toml");
3726
3676
  await import_fs3.default.promises.writeFile(pyprojectPath, content);
3727
3677
  }
3728
- const workspaceLockFile = pythonPackage?.workspaceLockFile;
3678
+ const workspaceLockFile = pythonPackage.workspaceLockFile;
3729
3679
  if (workspaceLockFile) {
3730
- lockPath = (0, import_path4.join)(rootDir, workspaceLockFile.path);
3680
+ lockPath = (0, import_path5.join)(rootDir, workspaceLockFile.path);
3731
3681
  } else {
3732
3682
  await uv.lock(
3733
3683
  projectDir,
@@ -3742,24 +3692,24 @@ async function ensureUvProject({
3742
3692
  }
3743
3693
  } else {
3744
3694
  projectDir = workPath;
3745
- pyprojectPath = (0, import_path4.join)(projectDir, "pyproject.toml");
3695
+ pyprojectPath = (0, import_path5.join)(projectDir, "pyproject.toml");
3746
3696
  console.log(
3747
3697
  "No Python manifest found; creating an empty pyproject.toml and uv.lock..."
3748
3698
  );
3749
3699
  const requiresPython = `~=${pythonVersion}.0`;
3750
- const minimalManifest = (0, import_python_analysis.createMinimalManifest)({
3700
+ const minimalManifest = (0, import_python_analysis2.createMinimalManifest)({
3751
3701
  name: "app",
3752
3702
  requiresPython,
3753
3703
  dependencies: []
3754
3704
  });
3755
- const content = (0, import_python_analysis.stringifyManifest)(minimalManifest);
3705
+ const content = (0, import_python_analysis2.stringifyManifest)(minimalManifest);
3756
3706
  await import_fs3.default.promises.writeFile(pyprojectPath, content);
3757
3707
  await uv.lock(
3758
3708
  projectDir,
3759
3709
  requireBinaryWheels ? { noBuild: true, upgrade: true } : void 0
3760
3710
  );
3761
3711
  }
3762
- const resolvedLockPath = lockPath && import_fs3.default.existsSync(lockPath) ? lockPath : (0, import_path4.join)(projectDir, "uv.lock");
3712
+ const resolvedLockPath = lockPath && import_fs3.default.existsSync(lockPath) ? lockPath : (0, import_path5.join)(projectDir, "uv.lock");
3763
3713
  return {
3764
3714
  projectDir,
3765
3715
  pyprojectPath,
@@ -3768,7 +3718,7 @@ async function ensureUvProject({
3768
3718
  };
3769
3719
  }
3770
3720
  async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
3771
- const target = targetDir ? (0, import_path4.join)(targetDir, resolveVendorDir()) : resolveVendorDir();
3721
+ const target = targetDir ? (0, import_path5.join)(targetDir, resolveVendorDir()) : resolveVendorDir();
3772
3722
  process.env.PIP_USER = "0";
3773
3723
  if (uvPath) {
3774
3724
  const uvArgs = [
@@ -3862,9 +3812,9 @@ async function installRequirementsFile({
3862
3812
  // src/dependency-externalizer.ts
3863
3813
  var import_fs4 = __toESM(require("fs"));
3864
3814
  var import_util = require("util");
3865
- var import_path5 = require("path");
3815
+ var import_path6 = require("path");
3866
3816
  var import_build_utils5 = require("@vercel/build-utils");
3867
- var import_python_analysis2 = require("@vercel/python-analysis");
3817
+ var import_python_analysis3 = require("@vercel/python-analysis");
3868
3818
  var readFile = (0, import_util.promisify)(import_fs4.default.readFile);
3869
3819
  var LAMBDA_SIZE_THRESHOLD_BYTES = 249 * 1024 * 1024;
3870
3820
  var LAMBDA_PACKING_TARGET_BYTES = 245 * 1024 * 1024;
@@ -4001,9 +3951,9 @@ To fix this, either:
4001
3951
  }
4002
3952
  let lockFile;
4003
3953
  try {
4004
- lockFile = (0, import_python_analysis2.parseUvLock)(lockContent, this.uvLockPath);
3954
+ lockFile = (0, import_python_analysis3.parseUvLock)(lockContent, this.uvLockPath);
4005
3955
  } catch (error) {
4006
- if (error instanceof import_python_analysis2.PythonAnalysisError) {
3956
+ if (error instanceof import_python_analysis3.PythonAnalysisError) {
4007
3957
  if (error.fileContent) {
4008
3958
  console.log(
4009
3959
  `Failed to parse "${error.path}". File content:
@@ -4024,7 +3974,7 @@ ${error.fileContent}`
4024
3974
  `Excluding project package "${this.projectName}" from runtime installation`
4025
3975
  );
4026
3976
  }
4027
- const classification = (0, import_python_analysis2.classifyPackages)({
3977
+ const classification = (0, import_python_analysis3.classifyPackages)({
4028
3978
  lockFile,
4029
3979
  excludePackages
4030
3980
  });
@@ -4088,11 +4038,11 @@ ${error.fileContent}`
4088
4038
  ...bundledPublic,
4089
4039
  ...this.alwaysBundlePackages
4090
4040
  ];
4091
- const projectDirRel = (0, import_path5.relative)(this.workPath, this.uvProjectDir);
4092
- const uvLockRel = (0, import_path5.relative)(this.workPath, this.uvLockPath);
4041
+ const projectDirRel = (0, import_path6.relative)(this.workPath, this.uvProjectDir);
4042
+ const uvLockRel = (0, import_path6.relative)(this.workPath, this.uvLockPath);
4093
4043
  const isOutsideWorkPath = projectDirRel.startsWith("..") || uvLockRel.startsWith("..");
4094
4044
  if (isOutsideWorkPath) {
4095
- const srcPyproject = (0, import_path5.join)(this.uvProjectDir, "pyproject.toml");
4045
+ const srcPyproject = (0, import_path6.join)(this.uvProjectDir, "pyproject.toml");
4096
4046
  files[`${UV_BUNDLE_DIR}/pyproject.toml`] = new import_build_utils5.FileFsRef({
4097
4047
  fsPath: srcPyproject
4098
4048
  });
@@ -4110,8 +4060,8 @@ ${error.fileContent}`
4110
4060
  if (process.env.VERCEL_BUILD_IMAGE) {
4111
4061
  try {
4112
4062
  const uvBinaryPath = await getUvBinaryForBundling(this.pythonPath);
4113
- const uvBundleDir = (0, import_path5.join)(this.workPath, UV_BUNDLE_DIR);
4114
- const uvLocalPath = (0, import_path5.join)(uvBundleDir, "uv");
4063
+ const uvBundleDir = (0, import_path6.join)(this.workPath, UV_BUNDLE_DIR);
4064
+ const uvLocalPath = (0, import_path6.join)(uvBundleDir, "uv");
4115
4065
  await import_fs4.default.promises.mkdir(uvBundleDir, { recursive: true });
4116
4066
  await import_fs4.default.promises.copyFile(uvBinaryPath, uvLocalPath);
4117
4067
  await import_fs4.default.promises.chmod(uvLocalPath, 493);
@@ -4151,30 +4101,30 @@ async function mirrorPackagesIntoVendor({
4151
4101
  if (includePackages && includePackages.length === 0) {
4152
4102
  return vendorFiles;
4153
4103
  }
4154
- const includeSet = includePackages ? new Set(includePackages.map(import_python_analysis2.normalizePackageName)) : null;
4104
+ const includeSet = includePackages ? new Set(includePackages.map(import_python_analysis3.normalizePackageName)) : null;
4155
4105
  const sitePackageDirs = await getVenvSitePackagesDirs(venvPath);
4156
4106
  for (const dir of sitePackageDirs) {
4157
4107
  if (!import_fs4.default.existsSync(dir))
4158
4108
  continue;
4159
- const resolvedDir = (0, import_path5.resolve)(dir);
4160
- const dirPrefix = resolvedDir + import_path5.sep;
4161
- const distributions = await (0, import_python_analysis2.scanDistributions)(dir);
4109
+ const resolvedDir = (0, import_path6.resolve)(dir);
4110
+ const dirPrefix = resolvedDir + import_path6.sep;
4111
+ const distributions = await (0, import_python_analysis3.scanDistributions)(dir);
4162
4112
  for (const [name, dist] of distributions) {
4163
4113
  if (includeSet && !includeSet.has(name))
4164
4114
  continue;
4165
4115
  for (const { path: rawPath } of dist.files) {
4166
- const filePath = rawPath.replaceAll("/", import_path5.sep);
4167
- if (!(0, import_path5.resolve)(resolvedDir, filePath).startsWith(dirPrefix)) {
4116
+ const filePath = rawPath.replaceAll("/", import_path6.sep);
4117
+ if (!(0, import_path6.resolve)(resolvedDir, filePath).startsWith(dirPrefix)) {
4168
4118
  continue;
4169
4119
  }
4170
- if (filePath.endsWith(".pyc") || filePath.split(import_path5.sep).includes("__pycache__")) {
4120
+ if (filePath.endsWith(".pyc") || filePath.split(import_path6.sep).includes("__pycache__")) {
4171
4121
  continue;
4172
4122
  }
4173
- const srcFsPath = (0, import_path5.join)(dir, filePath);
4123
+ const srcFsPath = (0, import_path6.join)(dir, filePath);
4174
4124
  if (!import_fs4.default.existsSync(srcFsPath)) {
4175
4125
  continue;
4176
4126
  }
4177
- const bundlePath = (0, import_path5.join)(vendorDirName, filePath).replace(/\\/g, "/");
4127
+ const bundlePath = (0, import_path6.join)(vendorDirName, filePath).replace(/\\/g, "/");
4178
4128
  vendorFiles[bundlePath] = new import_build_utils5.FileFsRef({ fsPath: srcFsPath });
4179
4129
  }
4180
4130
  }
@@ -4225,21 +4175,21 @@ async function calculatePerPackageSizes(venvPath) {
4225
4175
  for (const dir of sitePackageDirs) {
4226
4176
  if (!import_fs4.default.existsSync(dir))
4227
4177
  continue;
4228
- const resolvedDir = (0, import_path5.resolve)(dir);
4229
- const dirPrefix = resolvedDir + import_path5.sep;
4230
- const distributions = await (0, import_python_analysis2.scanDistributions)(dir);
4178
+ const resolvedDir = (0, import_path6.resolve)(dir);
4179
+ const dirPrefix = resolvedDir + import_path6.sep;
4180
+ const distributions = await (0, import_python_analysis3.scanDistributions)(dir);
4231
4181
  for (const [name, dist] of distributions) {
4232
4182
  let totalSize = 0;
4233
4183
  for (const { path: rawPath } of dist.files) {
4234
- const filePath = rawPath.replaceAll("/", import_path5.sep);
4235
- if (!(0, import_path5.resolve)(resolvedDir, filePath).startsWith(dirPrefix)) {
4184
+ const filePath = rawPath.replaceAll("/", import_path6.sep);
4185
+ if (!(0, import_path6.resolve)(resolvedDir, filePath).startsWith(dirPrefix)) {
4236
4186
  continue;
4237
4187
  }
4238
- if (filePath.endsWith(".pyc") || filePath.split(import_path5.sep).includes("__pycache__")) {
4188
+ if (filePath.endsWith(".pyc") || filePath.split(import_path6.sep).includes("__pycache__")) {
4239
4189
  continue;
4240
4190
  }
4241
4191
  try {
4242
- const stats = await import_fs4.default.promises.stat((0, import_path5.join)(dir, filePath));
4192
+ const stats = await import_fs4.default.promises.stat((0, import_path6.join)(dir, filePath));
4243
4193
  totalSize += stats.size;
4244
4194
  } catch {
4245
4195
  }
@@ -4250,19 +4200,16 @@ async function calculatePerPackageSizes(venvPath) {
4250
4200
  return sizes;
4251
4201
  }
4252
4202
 
4253
- // src/index.ts
4254
- var import_build_utils13 = require("@vercel/build-utils");
4255
-
4256
4203
  // src/start-dev-server.ts
4257
4204
  var import_child_process2 = require("child_process");
4258
4205
  var import_fs5 = require("fs");
4259
- var import_path7 = require("path");
4206
+ var import_path8 = require("path");
4260
4207
  var import_build_utils8 = require("@vercel/build-utils");
4261
4208
  var import_get_port = __toESM(require_get_port());
4262
4209
  var import_is_port_reachable = __toESM(require_is_port_reachable());
4263
4210
 
4264
4211
  // src/entrypoint.ts
4265
- var import_path6 = require("path");
4212
+ var import_path7 = require("path");
4266
4213
  var import_build_utils6 = require("@vercel/build-utils");
4267
4214
  var import_build_utils7 = require("@vercel/build-utils");
4268
4215
  var PYTHON_ENTRYPOINT_FILENAMES = [
@@ -4280,12 +4227,12 @@ var PYTHON_CANDIDATE_ENTRYPOINTS = getCandidateEntrypointsInDirs(
4280
4227
  function getCandidateEntrypointsInDirs(dirs) {
4281
4228
  return dirs.flatMap(
4282
4229
  (dir) => PYTHON_ENTRYPOINT_FILENAMES.map(
4283
- (filename) => import_path6.posix.join(dir, `${filename}.py`)
4230
+ (filename) => import_path7.posix.join(dir, `${filename}.py`)
4284
4231
  )
4285
4232
  );
4286
4233
  }
4287
4234
  async function getPyprojectEntrypoint(workPath) {
4288
- const pyprojectData = await (0, import_build_utils7.readConfigFile)((0, import_path6.join)(workPath, "pyproject.toml"));
4235
+ const pyprojectData = await (0, import_build_utils7.readConfigFile)((0, import_path7.join)(workPath, "pyproject.toml"));
4289
4236
  if (!pyprojectData)
4290
4237
  return null;
4291
4238
  const scripts = pyprojectData.project?.scripts;
@@ -4364,10 +4311,10 @@ async function detectDjangoPythonEntrypoint(workPath, configuredEntrypoint) {
4364
4311
  )
4365
4312
  ];
4366
4313
  for (const rootDir of rootDirs) {
4367
- const currPath = (0, import_path6.join)(workPath, rootDir);
4314
+ const currPath = (0, import_path7.join)(workPath, rootDir);
4368
4315
  const wsgiEntry = await (0, import_build_utils6.getDjangoEntrypoint)(currPath);
4369
4316
  if (wsgiEntry) {
4370
- const fullWsgiEntry = import_path6.posix.join(rootDir, wsgiEntry);
4317
+ const fullWsgiEntry = import_path7.posix.join(rootDir, wsgiEntry);
4371
4318
  if (fsFiles[fullWsgiEntry]) {
4372
4319
  (0, import_build_utils6.debug)(`Using Django WSGI entrypoint: ${fullWsgiEntry}`);
4373
4320
  return fullWsgiEntry;
@@ -4390,7 +4337,7 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint)
4390
4337
  }
4391
4338
 
4392
4339
  // src/start-dev-server.ts
4393
- var import_python_analysis3 = require("@vercel/python-analysis");
4340
+ var import_python_analysis4 = require("@vercel/python-analysis");
4394
4341
  var DEV_SERVER_STARTUP_TIMEOUT = 1e4;
4395
4342
  function silenceNodeWarnings() {
4396
4343
  const original = process.emitWarning.bind(
@@ -4463,21 +4410,23 @@ async function syncDependencies({
4463
4410
  onStdout,
4464
4411
  onStderr
4465
4412
  }) {
4466
- const installInfo = await detectInstallSource({
4467
- workPath,
4468
- entryDirectory: "."
4413
+ const pythonPackage = await discoverPackage({
4414
+ entrypointDir: workPath,
4415
+ rootDir: workPath
4469
4416
  });
4470
- let { manifestType, manifestPath } = installInfo;
4471
- const manifest = installInfo.pythonPackage?.manifest;
4417
+ const installInfo = detectInstallSource(pythonPackage, workPath);
4418
+ const { manifestType } = installInfo;
4419
+ let { manifestPath } = installInfo;
4420
+ const manifest = pythonPackage.manifest;
4472
4421
  if (!manifestType || !manifestPath) {
4473
4422
  (0, import_build_utils8.debug)("No Python project manifest found, skipping dependency sync");
4474
4423
  return;
4475
4424
  }
4476
4425
  if (manifest?.origin && manifestType === "pyproject.toml") {
4477
- const syncDir = (0, import_path7.join)(workPath, ".vercel", "python", "sync");
4426
+ const syncDir = (0, import_path8.join)(workPath, ".vercel", "python", "sync");
4478
4427
  (0, import_fs5.mkdirSync)(syncDir, { recursive: true });
4479
- const tempPyproject = (0, import_path7.join)(syncDir, "pyproject.toml");
4480
- const content = (0, import_python_analysis3.stringifyManifest)(manifest.data);
4428
+ const tempPyproject = (0, import_path8.join)(syncDir, "pyproject.toml");
4429
+ const content = (0, import_python_analysis4.stringifyManifest)(manifest.data);
4481
4430
  (0, import_fs5.writeFileSync)(tempPyproject, content, "utf8");
4482
4431
  manifestPath = tempPyproject;
4483
4432
  (0, import_build_utils8.debug)(
@@ -4528,7 +4477,7 @@ async function runSync({
4528
4477
  onStdout,
4529
4478
  onStderr
4530
4479
  }) {
4531
- const projectDir = (0, import_path7.dirname)(manifestPath);
4480
+ const projectDir = (0, import_path8.dirname)(manifestPath);
4532
4481
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
4533
4482
  let spawnCmd;
4534
4483
  let spawnArgs;
@@ -4638,18 +4587,18 @@ function installGlobalCleanupHandlers() {
4638
4587
  }
4639
4588
  function createDevShim(workPath, entry, modulePath) {
4640
4589
  try {
4641
- const vercelPythonDir = (0, import_path7.join)(workPath, ".vercel", "python");
4590
+ const vercelPythonDir = (0, import_path8.join)(workPath, ".vercel", "python");
4642
4591
  (0, import_fs5.mkdirSync)(vercelPythonDir, { recursive: true });
4643
4592
  let qualifiedModule = modulePath;
4644
4593
  let extraPythonPath;
4645
- if ((0, import_fs5.existsSync)((0, import_path7.join)(workPath, "__init__.py"))) {
4646
- const pkgName = (0, import_path7.basename)(workPath);
4594
+ if ((0, import_fs5.existsSync)((0, import_path8.join)(workPath, "__init__.py"))) {
4595
+ const pkgName = (0, import_path8.basename)(workPath);
4647
4596
  qualifiedModule = `${pkgName}.${modulePath}`;
4648
- extraPythonPath = (0, import_path7.dirname)(workPath);
4597
+ extraPythonPath = (0, import_path8.dirname)(workPath);
4649
4598
  }
4650
- const entryAbs = (0, import_path7.join)(workPath, entry);
4651
- const shimPath = (0, import_path7.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
4652
- const templatePath = (0, import_path7.join)(__dirname, "..", `${DEV_SHIM_MODULE}.py`);
4599
+ const entryAbs = (0, import_path8.join)(workPath, entry);
4600
+ const shimPath = (0, import_path8.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
4601
+ const templatePath = (0, import_path8.join)(__dirname, "..", `${DEV_SHIM_MODULE}.py`);
4653
4602
  const template = (0, import_fs5.readFileSync)(templatePath, "utf8");
4654
4603
  const shimSource = template.replace(/__VC_DEV_MODULE_NAME__/g, qualifiedModule).replace(/__VC_DEV_ENTRY_ABS__/g, entryAbs);
4655
4604
  (0, import_fs5.writeFileSync)(shimPath, shimSource, "utf8");
@@ -4666,13 +4615,13 @@ async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath)
4666
4615
  (0, import_build_utils8.debug)(`Using existing virtualenv at ${venvRoot} for multi-service dev`);
4667
4616
  return { command: pythonCmd, args: [] };
4668
4617
  }
4669
- const venvPath = (0, import_path7.join)(workPath, ".venv");
4618
+ const venvPath = (0, import_path8.join)(workPath, ".venv");
4670
4619
  await ensureVenv({ pythonPath: systemPython, venvPath, uvPath, quiet: true });
4671
4620
  (0, import_build_utils8.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
4672
4621
  const pythonBin = getVenvPythonBin(venvPath);
4673
4622
  const binDir = getVenvBinDir(venvPath);
4674
4623
  env.VIRTUAL_ENV = venvPath;
4675
- env.PATH = `${binDir}${import_path7.delimiter}${env.PATH || ""}`;
4624
+ env.PATH = `${binDir}${import_path8.delimiter}${env.PATH || ""}`;
4676
4625
  return { command: pythonBin, args: [] };
4677
4626
  }
4678
4627
  var startDevServer = async (opts) => {
@@ -4820,7 +4769,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
4820
4769
  env.PORT = `${port}`;
4821
4770
  const devShim = createDevShim(workPath, entry, modulePath);
4822
4771
  if (devShim) {
4823
- const vercelPythonDir = (0, import_path7.join)(workPath, ".vercel", "python");
4772
+ const vercelPythonDir = (0, import_path8.join)(workPath, ".vercel", "python");
4824
4773
  const pathParts = [vercelPythonDir];
4825
4774
  if (devShim.extraPythonPath) {
4826
4775
  pathParts.push(devShim.extraPythonPath);
@@ -4829,7 +4778,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
4829
4778
  if (existingPythonPath) {
4830
4779
  pathParts.push(existingPythonPath);
4831
4780
  }
4832
- env.PYTHONPATH = pathParts.join(import_path7.delimiter);
4781
+ env.PYTHONPATH = pathParts.join(import_path8.delimiter);
4833
4782
  }
4834
4783
  const moduleToRun = devShim?.module || modulePath;
4835
4784
  const pythonArgs = ["-u", "-m", moduleToRun];
@@ -4889,7 +4838,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
4889
4838
 
4890
4839
  // src/quirks/index.ts
4891
4840
  var import_build_utils11 = require("@vercel/build-utils");
4892
- var import_python_analysis5 = require("@vercel/python-analysis");
4841
+ var import_python_analysis6 = require("@vercel/python-analysis");
4893
4842
 
4894
4843
  // src/quirks/matplotlib.ts
4895
4844
  var matplotlibQuirk = {
@@ -4903,7 +4852,7 @@ var matplotlibQuirk = {
4903
4852
 
4904
4853
  // src/quirks/litellm.ts
4905
4854
  var import_fs6 = __toESM(require("fs"));
4906
- var import_path8 = require("path");
4855
+ var import_path9 = require("path");
4907
4856
  var import_build_utils9 = require("@vercel/build-utils");
4908
4857
  var LAMBDA_ROOT = "/var/task";
4909
4858
  var CONFIG_CANDIDATES = [
@@ -4914,7 +4863,7 @@ var CONFIG_CANDIDATES = [
4914
4863
  ];
4915
4864
  async function findConfigFile(workPath) {
4916
4865
  for (const name of CONFIG_CANDIDATES) {
4917
- const candidate = (0, import_path8.join)(workPath, name);
4866
+ const candidate = (0, import_path9.join)(workPath, name);
4918
4867
  try {
4919
4868
  await import_fs6.default.promises.access(candidate);
4920
4869
  return name;
@@ -4931,7 +4880,7 @@ var litellmQuirk = {
4931
4880
  const env = {};
4932
4881
  const sitePackagesDirs = await getVenvSitePackagesDirs(ctx.venvPath);
4933
4882
  for (const sitePackages of sitePackagesDirs) {
4934
- const schemaPath = (0, import_path8.join)(
4883
+ const schemaPath = (0, import_path9.join)(
4935
4884
  sitePackages,
4936
4885
  "litellm",
4937
4886
  "proxy",
@@ -4952,8 +4901,8 @@ var litellmQuirk = {
4952
4901
  const configName = await findConfigFile(ctx.workPath);
4953
4902
  if (configName) {
4954
4903
  (0, import_build_utils9.debug)(`LiteLLM quirk: found config at ${configName}`);
4955
- buildEnv.CONFIG_FILE_PATH = (0, import_path8.join)(ctx.workPath, configName);
4956
- env.CONFIG_FILE_PATH = (0, import_path8.join)(LAMBDA_ROOT, configName);
4904
+ buildEnv.CONFIG_FILE_PATH = (0, import_path9.join)(ctx.workPath, configName);
4905
+ env.CONFIG_FILE_PATH = (0, import_path9.join)(LAMBDA_ROOT, configName);
4957
4906
  }
4958
4907
  } else {
4959
4908
  (0, import_build_utils9.debug)(
@@ -4966,10 +4915,10 @@ var litellmQuirk = {
4966
4915
 
4967
4916
  // src/quirks/prisma.ts
4968
4917
  var import_fs7 = __toESM(require("fs"));
4969
- var import_path9 = require("path");
4918
+ var import_path10 = require("path");
4970
4919
  var import_execa4 = __toESM(require_execa());
4971
4920
  var import_build_utils10 = require("@vercel/build-utils");
4972
- var import_python_analysis4 = require("@vercel/python-analysis");
4921
+ var import_python_analysis5 = require("@vercel/python-analysis");
4973
4922
  function execErrorMessage(err) {
4974
4923
  if (err != null && typeof err === "object" && "stderr" in err) {
4975
4924
  const stderr = String(err.stderr);
@@ -5005,7 +4954,7 @@ model DummyModel {
5005
4954
  async function findUserSchema(workPath) {
5006
4955
  const envPath = process.env.PRISMA_SCHEMA_PATH;
5007
4956
  if (envPath) {
5008
- const resolved = (0, import_path9.isAbsolute)(envPath) ? envPath : (0, import_path9.join)(workPath, envPath);
4957
+ const resolved = (0, import_path10.isAbsolute)(envPath) ? envPath : (0, import_path10.join)(workPath, envPath);
5009
4958
  try {
5010
4959
  await import_fs7.default.promises.access(resolved);
5011
4960
  return resolved;
@@ -5015,8 +4964,8 @@ async function findUserSchema(workPath) {
5015
4964
  }
5016
4965
  }
5017
4966
  const candidates = [
5018
- (0, import_path9.join)(workPath, "schema.prisma"),
5019
- (0, import_path9.join)(workPath, "prisma", "schema.prisma")
4967
+ (0, import_path10.join)(workPath, "schema.prisma"),
4968
+ (0, import_path10.join)(workPath, "prisma", "schema.prisma")
5020
4969
  ];
5021
4970
  for (const candidate of candidates) {
5022
4971
  try {
@@ -5038,20 +4987,20 @@ async function collectFiles(dir, base) {
5038
4987
  for (const entry of entries) {
5039
4988
  if (entry.name === "__pycache__")
5040
4989
  continue;
5041
- const full = (0, import_path9.join)(dir, entry.name);
4990
+ const full = (0, import_path10.join)(dir, entry.name);
5042
4991
  if (entry.isDirectory()) {
5043
4992
  result.push(...await collectFiles(full, base));
5044
4993
  } else {
5045
- result.push((0, import_path9.relative)(base, full));
4994
+ result.push((0, import_path10.relative)(base, full));
5046
4995
  }
5047
4996
  }
5048
4997
  return result;
5049
4998
  }
5050
4999
  async function cleanCacheArtifacts(cacheDir, extras = []) {
5051
5000
  const paths = [
5052
- (0, import_path9.join)(cacheDir, "node_modules"),
5053
- (0, import_path9.join)(cacheDir, "package.json"),
5054
- (0, import_path9.join)(cacheDir, "package-lock.json"),
5001
+ (0, import_path10.join)(cacheDir, "node_modules"),
5002
+ (0, import_path10.join)(cacheDir, "package.json"),
5003
+ (0, import_path10.join)(cacheDir, "package-lock.json"),
5055
5004
  ...extras
5056
5005
  ];
5057
5006
  for (const p of paths) {
@@ -5080,7 +5029,7 @@ var prismaQuirk = {
5080
5029
  async run(ctx) {
5081
5030
  const { venvPath, pythonEnv, workPath } = ctx;
5082
5031
  const pythonPath = getVenvPythonBin(venvPath);
5083
- const runtimeCacheDir = (0, import_path9.join)(
5032
+ const runtimeCacheDir = (0, import_path10.join)(
5084
5033
  LAMBDA_ROOT2,
5085
5034
  resolveVendorDir(),
5086
5035
  "prisma",
@@ -5090,7 +5039,7 @@ var prismaQuirk = {
5090
5039
  let sitePackages;
5091
5040
  for (const dir of sitePackagesDirs) {
5092
5041
  try {
5093
- await import_fs7.default.promises.access((0, import_path9.join)(dir, "prisma"));
5042
+ await import_fs7.default.promises.access((0, import_path10.join)(dir, "prisma"));
5094
5043
  sitePackages = dir;
5095
5044
  break;
5096
5045
  } catch {
@@ -5102,14 +5051,14 @@ var prismaQuirk = {
5102
5051
  );
5103
5052
  return {};
5104
5053
  }
5105
- const cacheDir = (0, import_path9.join)(sitePackages, "prisma", "__bincache__");
5054
+ const cacheDir = (0, import_path10.join)(sitePackages, "prisma", "__bincache__");
5106
5055
  await import_fs7.default.promises.mkdir(cacheDir, { recursive: true });
5107
5056
  const generateEnv = {
5108
5057
  ...pythonEnv,
5109
5058
  PRISMA_BINARY_CACHE_DIR: cacheDir
5110
5059
  };
5111
- const generatedDir = (0, import_path9.join)(workPath, "_prisma_generated");
5112
- const dummySchemaPath = (0, import_path9.join)(workPath, DUMMY_SCHEMA_NAME);
5060
+ const generatedDir = (0, import_path10.join)(workPath, "_prisma_generated");
5061
+ const dummySchemaPath = (0, import_path10.join)(workPath, DUMMY_SCHEMA_NAME);
5113
5062
  await import_fs7.default.promises.writeFile(
5114
5063
  dummySchemaPath,
5115
5064
  buildDummySchema(generatedDir)
@@ -5138,15 +5087,15 @@ var prismaQuirk = {
5138
5087
  }
5139
5088
  const srcBinaryPrefix = `query-engine-${getLambdaBinaryTarget()}`;
5140
5089
  const runtimeName = `prisma-query-engine-rhel-openssl-${RUNTIME_OPENSSL_VERSION}.x`;
5141
- const nodeModulesDir = (0, import_path9.join)(cacheDir, "node_modules", "prisma");
5090
+ const nodeModulesDir = (0, import_path10.join)(cacheDir, "node_modules", "prisma");
5142
5091
  let engineCopied = false;
5143
5092
  try {
5144
5093
  const entries = await import_fs7.default.promises.readdir(nodeModulesDir);
5145
5094
  for (const entry of entries) {
5146
5095
  if (!entry.startsWith(srcBinaryPrefix))
5147
5096
  continue;
5148
- const srcPath = (0, import_path9.join)(nodeModulesDir, entry);
5149
- const destPath = (0, import_path9.join)(cacheDir, runtimeName);
5097
+ const srcPath = (0, import_path10.join)(nodeModulesDir, entry);
5098
+ const destPath = (0, import_path10.join)(cacheDir, runtimeName);
5150
5099
  try {
5151
5100
  await import_fs7.default.promises.access(destPath);
5152
5101
  (0, import_build_utils10.debug)(`Engine binary: ${runtimeName} already exists, skipping`);
@@ -5169,7 +5118,7 @@ var prismaQuirk = {
5169
5118
  message: `could not find engine binary matching "${srcBinaryPrefix}*" in "${nodeModulesDir}". This may indicate an incompatible prisma version or an unsupported platform (${process.arch}).`
5170
5119
  });
5171
5120
  }
5172
- const shimPath = (0, import_path9.join)(cacheDir, "openssl");
5121
+ const shimPath = (0, import_path10.join)(cacheDir, "openssl");
5173
5122
  await import_fs7.default.promises.writeFile(
5174
5123
  shimPath,
5175
5124
  `#!/bin/sh
@@ -5225,10 +5174,10 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
5225
5174
  }
5226
5175
  try {
5227
5176
  const allFiles = await collectFiles(
5228
- (0, import_path9.join)(sitePackages, "prisma"),
5177
+ (0, import_path10.join)(sitePackages, "prisma"),
5229
5178
  sitePackages
5230
5179
  );
5231
- const count = await (0, import_python_analysis4.extendDistRecord)(sitePackages, "prisma", allFiles);
5180
+ const count = await (0, import_python_analysis5.extendDistRecord)(sitePackages, "prisma", allFiles);
5232
5181
  if (count > 0) {
5233
5182
  (0, import_build_utils10.debug)(`Appended ${count} entries to prisma RECORD`);
5234
5183
  }
@@ -5253,7 +5202,7 @@ var quirks = [litellmQuirk, prismaQuirk, matplotlibQuirk];
5253
5202
  function toposortQuirks(activated) {
5254
5203
  const nameToQuirk = /* @__PURE__ */ new Map();
5255
5204
  for (const q of activated) {
5256
- nameToQuirk.set((0, import_python_analysis5.normalizePackageName)(q.dependency), q);
5205
+ nameToQuirk.set((0, import_python_analysis6.normalizePackageName)(q.dependency), q);
5257
5206
  }
5258
5207
  const adj = /* @__PURE__ */ new Map();
5259
5208
  const inDegree = /* @__PURE__ */ new Map();
@@ -5264,7 +5213,7 @@ function toposortQuirks(activated) {
5264
5213
  for (const q of activated) {
5265
5214
  if (q.runsBefore) {
5266
5215
  for (const dep of q.runsBefore) {
5267
- const target = nameToQuirk.get((0, import_python_analysis5.normalizePackageName)(dep));
5216
+ const target = nameToQuirk.get((0, import_python_analysis6.normalizePackageName)(dep));
5268
5217
  if (target) {
5269
5218
  adj.get(q).add(target);
5270
5219
  inDegree.set(target, inDegree.get(target) + 1);
@@ -5273,7 +5222,7 @@ function toposortQuirks(activated) {
5273
5222
  }
5274
5223
  if (q.runsAfter) {
5275
5224
  for (const dep of q.runsAfter) {
5276
- const source = nameToQuirk.get((0, import_python_analysis5.normalizePackageName)(dep));
5225
+ const source = nameToQuirk.get((0, import_python_analysis6.normalizePackageName)(dep));
5277
5226
  if (source) {
5278
5227
  adj.get(source).add(q);
5279
5228
  inDegree.set(q, inDegree.get(q) + 1);
@@ -5314,14 +5263,14 @@ async function runQuirks(ctx) {
5314
5263
  const installedNames = /* @__PURE__ */ new Set();
5315
5264
  const sitePackageDirs = await getVenvSitePackagesDirs(ctx.venvPath);
5316
5265
  for (const dir of sitePackageDirs) {
5317
- const distributions = await (0, import_python_analysis5.scanDistributions)(dir);
5266
+ const distributions = await (0, import_python_analysis6.scanDistributions)(dir);
5318
5267
  for (const name of distributions.keys()) {
5319
- installedNames.add((0, import_python_analysis5.normalizePackageName)(name));
5268
+ installedNames.add((0, import_python_analysis6.normalizePackageName)(name));
5320
5269
  }
5321
5270
  }
5322
5271
  const activated = quirks.filter((quirk) => {
5323
5272
  const installed = installedNames.has(
5324
- (0, import_python_analysis5.normalizePackageName)(quirk.dependency)
5273
+ (0, import_python_analysis6.normalizePackageName)(quirk.dependency)
5325
5274
  );
5326
5275
  if (!installed) {
5327
5276
  (0, import_build_utils11.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
@@ -5351,8 +5300,7 @@ async function runQuirks(ctx) {
5351
5300
  }
5352
5301
 
5353
5302
  // src/index.ts
5354
- var readFile2 = (0, import_util2.promisify)(import_fs8.default.readFile);
5355
- var writeFile = (0, import_util2.promisify)(import_fs8.default.writeFile);
5303
+ var writeFile = import_fs8.default.promises.writeFile;
5356
5304
  var version = 3;
5357
5305
  async function downloadFilesInWorkPath({
5358
5306
  entrypoint,
@@ -5363,8 +5311,8 @@ async function downloadFilesInWorkPath({
5363
5311
  (0, import_build_utils12.debug)("Downloading user files...");
5364
5312
  let downloadedFiles = await (0, import_build_utils12.download)(files, workPath, meta);
5365
5313
  if (meta.isDev) {
5366
- const { devCacheDir = (0, import_path10.join)(workPath, ".now", "cache") } = meta;
5367
- const destCache = (0, import_path10.join)(devCacheDir, (0, import_path10.basename)(entrypoint, ".py"));
5314
+ const { devCacheDir = (0, import_path11.join)(workPath, ".now", "cache") } = meta;
5315
+ const destCache = (0, import_path11.join)(devCacheDir, (0, import_path11.basename)(entrypoint, ".py"));
5368
5316
  await (0, import_build_utils12.download)(downloadedFiles, destCache);
5369
5317
  downloadedFiles = await (0, import_build_utils12.glob)("**", destCache);
5370
5318
  workPath = destCache;
@@ -5382,6 +5330,7 @@ var build = async ({
5382
5330
  }) => {
5383
5331
  const builderSpan = parentSpan ?? new import_build_utils12.Span({ name: "vc.builder" });
5384
5332
  const framework = config?.framework;
5333
+ const shouldInstallVercelWorkers = config?.hasWorkerServices === true;
5385
5334
  let spawnEnv;
5386
5335
  let projectInstallCommand;
5387
5336
  let hasCustomCommand = false;
@@ -5394,7 +5343,7 @@ var build = async ({
5394
5343
  });
5395
5344
  try {
5396
5345
  if (meta.isDev) {
5397
- const setupCfg = (0, import_path10.join)(workPath, "setup.cfg");
5346
+ const setupCfg = (0, import_path11.join)(workPath, "setup.cfg");
5398
5347
  await writeFile(setupCfg, "[install]\nprefix=\n");
5399
5348
  }
5400
5349
  } catch (err) {
@@ -5423,106 +5372,39 @@ var build = async ({
5423
5372
  });
5424
5373
  }
5425
5374
  }
5426
- const entryDirectory = (0, import_path10.dirname)(entrypoint);
5427
- const pyprojectDir = findDir({
5428
- file: "pyproject.toml",
5429
- entryDirectory,
5430
- workPath,
5431
- fsFiles
5432
- });
5433
- const pipfileLockDir = findDir({
5434
- file: "Pipfile.lock",
5435
- entryDirectory,
5436
- workPath,
5437
- fsFiles
5438
- });
5439
- const pythonVersionFileDir = findDir({
5440
- file: ".python-version",
5441
- entryDirectory,
5442
- workPath,
5443
- fsFiles
5444
- });
5445
- const { pythonVersion, declaredPythonVersion } = await builderSpan.child("vc.builder.python.version").trace(async (versionSpan) => {
5446
- let declared;
5447
- if (pythonVersionFileDir) {
5448
- try {
5449
- const content = await readFile2(
5450
- (0, import_path10.join)(pythonVersionFileDir, ".python-version"),
5451
- "utf8"
5452
- );
5453
- const version2 = parsePythonVersionFile(content);
5454
- if (version2) {
5455
- declared = { version: version2, source: ".python-version" };
5456
- (0, import_build_utils12.debug)(`Found Python version ${version2} in .python-version`);
5457
- }
5458
- } catch (err) {
5459
- (0, import_build_utils12.debug)("Failed to read .python-version file", err);
5460
- }
5461
- }
5462
- if (!declared && pyprojectDir) {
5463
- let requiresPython;
5464
- try {
5465
- const pyproject = await (0, import_build_utils13.readConfigFile)((0, import_path10.join)(pyprojectDir, "pyproject.toml"));
5466
- requiresPython = pyproject?.project?.["requires-python"];
5467
- } catch (err) {
5468
- (0, import_build_utils12.debug)("Failed to parse pyproject.toml", err);
5469
- }
5470
- if (typeof requiresPython === "string" && requiresPython.trim()) {
5471
- declared = {
5472
- version: requiresPython.trim(),
5473
- source: "pyproject.toml"
5474
- };
5475
- (0, import_build_utils12.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
5476
- }
5477
- }
5478
- if (!declared && pipfileLockDir) {
5479
- let lock = {};
5480
- const pipfileLockPath = (0, import_path10.join)(pipfileLockDir, "Pipfile.lock");
5481
- try {
5482
- const pipfileLockContent = await readFile2(pipfileLockPath, "utf8");
5483
- try {
5484
- lock = JSON.parse(pipfileLockContent);
5485
- } catch (err) {
5486
- console.log(
5487
- `Failed to parse "Pipfile.lock". File content:
5488
- ${pipfileLockContent}`
5489
- );
5490
- throw err;
5491
- }
5492
- } catch (err) {
5493
- throw new import_build_utils12.NowBuildError({
5494
- code: "INVALID_PIPFILE_LOCK",
5495
- message: "Unable to parse Pipfile.lock"
5496
- });
5497
- }
5498
- const pyFromLock = lock?._meta?.requires?.python_version;
5499
- if (pyFromLock) {
5500
- declared = { version: pyFromLock, source: "Pipfile.lock" };
5501
- (0, import_build_utils12.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
5502
- }
5503
- }
5504
- const resolved = getSupportedPythonVersion({
5375
+ const entryDirectory = (0, import_path11.dirname)(entrypoint);
5376
+ const entrypointAbsDir = (0, import_path11.join)(workPath, entryDirectory);
5377
+ const rootDir = repoRootPath ?? workPath;
5378
+ const pythonPackage = await builderSpan.child("vc.builder.python.discover").trace(
5379
+ () => discoverPackage({
5380
+ entrypointDir: entrypointAbsDir,
5381
+ rootDir
5382
+ })
5383
+ );
5384
+ const { pythonVersion, pinVersionFilePath } = await builderSpan.child("vc.builder.python.version").trace((versionSpan) => {
5385
+ const resolution = resolvePythonVersion({
5505
5386
  isDev: meta.isDev,
5506
- declaredPythonVersion: declared
5387
+ pythonPackage,
5388
+ rootDir
5507
5389
  });
5508
5390
  versionSpan.setAttributes({
5509
- "python.version": resolved.version,
5510
- "python.versionSource": declared?.source
5391
+ "python.version": pythonVersionString(resolution.pythonVersion),
5392
+ "python.versionSource": resolution.versionSource
5511
5393
  });
5512
- return { pythonVersion: resolved, declaredPythonVersion: declared };
5394
+ return resolution;
5513
5395
  });
5514
- const selectedVersionTuple = parseVersionTuple(pythonVersion.version);
5515
- const defaultVersionTuple = parseVersionTuple(DEFAULT_PYTHON_VERSION);
5516
- if (!pythonVersionFileDir && pyprojectDir && declaredPythonVersion?.source === "pyproject.toml" && selectedVersionTuple && defaultVersionTuple && compareTuples(selectedVersionTuple, defaultVersionTuple) <= 0) {
5517
- const pythonVersionFilePath = (0, import_path10.join)(pyprojectDir, ".python-version");
5518
- await writeFile(pythonVersionFilePath, `${pythonVersion.version}
5519
- `);
5396
+ if (pinVersionFilePath) {
5520
5397
  console.log(
5521
- `Writing .python-version file with version ${pythonVersion.version}`
5398
+ `Writing .python-version file with version ${pythonVersionString(pythonVersion)}`
5399
+ );
5400
+ await writeFile(
5401
+ pinVersionFilePath,
5402
+ `${pythonVersionString(pythonVersion)}
5403
+ `
5522
5404
  );
5523
5405
  }
5524
5406
  fsFiles = await (0, import_build_utils12.glob)("**", workPath);
5525
- const venvPath = (0, import_path10.join)(workPath, ".vercel", "python", ".venv");
5407
+ const venvPath = (0, import_path11.join)(workPath, ".vercel", "python", ".venv");
5526
5408
  await builderSpan.child("vc.builder.python.venv").trace(async () => {
5527
5409
  await ensureVenv({
5528
5410
  pythonPath: pythonVersion.pythonPath,
@@ -5601,21 +5483,16 @@ ${pipfileLockContent}`
5601
5483
  if (!assumeDepsInstalled) {
5602
5484
  const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
5603
5485
  workPath,
5604
- entryDirectory,
5605
- repoRootPath,
5606
- pythonVersion: pythonVersion.version,
5486
+ rootDir,
5487
+ pythonPackage,
5488
+ pythonVersion: pythonVersionString(pythonVersion),
5607
5489
  uv,
5608
5490
  generateLockFile: true,
5609
5491
  requireBinaryWheels: false
5610
5492
  });
5611
5493
  uvLockPath = lockPath;
5612
5494
  uvProjectDir = projectDir;
5613
- const installInfo = await detectInstallSource({
5614
- workPath,
5615
- entryDirectory,
5616
- repoRootPath
5617
- });
5618
- projectName = installInfo.pythonPackage?.manifest?.data?.project?.name;
5495
+ projectName = pythonPackage?.manifest?.data?.project?.name;
5619
5496
  if (lockFileProvidedByUser) {
5620
5497
  try {
5621
5498
  await uv.sync({
@@ -5665,9 +5542,18 @@ ${pipfileLockContent}`
5665
5542
  (0, import_build_utils12.debug)(`Installing ${runtimeDep}`);
5666
5543
  await uv.pip({
5667
5544
  venvPath,
5668
- projectDir: (0, import_path10.join)(workPath, entryDirectory),
5545
+ projectDir: (0, import_path11.join)(workPath, entryDirectory),
5669
5546
  args: ["install", runtimeDep]
5670
5547
  });
5548
+ if (shouldInstallVercelWorkers) {
5549
+ const workersDep = baseEnv.VERCEL_WORKERS_PYTHON || `vercel-workers==${VERCEL_WORKERS_VERSION}`;
5550
+ (0, import_build_utils12.debug)(`Installing ${workersDep}`);
5551
+ await uv.pip({
5552
+ venvPath,
5553
+ projectDir: (0, import_path11.join)(workPath, entryDirectory),
5554
+ args: ["install", workersDep]
5555
+ });
5556
+ }
5671
5557
  const quirksResult = await runQuirks({ venvPath, pythonEnv, workPath });
5672
5558
  if (quirksResult.buildEnv) {
5673
5559
  Object.assign(pythonEnv, quirksResult.buildEnv);
@@ -5752,7 +5638,10 @@ from vercel_runtime.vc_init import vc_handler
5752
5638
  noBuildCheckFailed,
5753
5639
  pythonPath: pythonVersion.pythonPath,
5754
5640
  hasCustomCommand,
5755
- alwaysBundlePackages: quirksResult.alwaysBundlePackages
5641
+ alwaysBundlePackages: [
5642
+ ...quirksResult.alwaysBundlePackages ?? [],
5643
+ ...shouldInstallVercelWorkers ? ["vercel-workers", "vercel_workers"] : []
5644
+ ]
5756
5645
  });
5757
5646
  await builderSpan.child("vc.builder.python.bundle").trace(async (bundleSpan) => {
5758
5647
  const depAnalysis = await depExternalizer.analyze(files);
@@ -5806,7 +5695,7 @@ var defaultShouldServe = ({
5806
5695
  if (entrypoint === requestPath && hasProp(files, entrypoint)) {
5807
5696
  return true;
5808
5697
  }
5809
- const { dir, name } = (0, import_path10.parse)(entrypoint);
5698
+ const { dir, name } = (0, import_path11.parse)(entrypoint);
5810
5699
  if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
5811
5700
  return true;
5812
5701
  }
@@ -5815,16 +5704,6 @@ var defaultShouldServe = ({
5815
5704
  function hasProp(obj, key) {
5816
5705
  return Object.hasOwnProperty.call(obj, key);
5817
5706
  }
5818
- function parsePythonVersionFile(content) {
5819
- const lines = content.split("\n");
5820
- for (const line of lines) {
5821
- const trimmed = line.trim();
5822
- if (!trimmed || trimmed.startsWith("#"))
5823
- continue;
5824
- return trimmed;
5825
- }
5826
- return void 0;
5827
- }
5828
5707
  // Annotate the CommonJS export names for ESM import in node:
5829
5708
  0 && (module.exports = {
5830
5709
  build,