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