@vercel/python 6.23.0 → 6.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2647,6 +2647,360 @@ ${stderr}${stdout}`;
2647
2647
  }
2648
2648
  });
2649
2649
 
2650
+ // ../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/process.js
2651
+ var require_process = __commonJS({
2652
+ "../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/process.js"(exports, module2) {
2653
+ "use strict";
2654
+ var isLinux = () => process.platform === "linux";
2655
+ var report = null;
2656
+ var getReport = () => {
2657
+ if (!report) {
2658
+ if (isLinux() && process.report) {
2659
+ const orig = process.report.excludeNetwork;
2660
+ process.report.excludeNetwork = true;
2661
+ report = process.report.getReport();
2662
+ process.report.excludeNetwork = orig;
2663
+ } else {
2664
+ report = {};
2665
+ }
2666
+ }
2667
+ return report;
2668
+ };
2669
+ module2.exports = { isLinux, getReport };
2670
+ }
2671
+ });
2672
+
2673
+ // ../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/filesystem.js
2674
+ var require_filesystem = __commonJS({
2675
+ "../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/filesystem.js"(exports, module2) {
2676
+ "use strict";
2677
+ var fs10 = require("fs");
2678
+ var LDD_PATH = "/usr/bin/ldd";
2679
+ var SELF_PATH = "/proc/self/exe";
2680
+ var MAX_LENGTH = 2048;
2681
+ var readFileSync2 = (path) => {
2682
+ const fd = fs10.openSync(path, "r");
2683
+ const buffer = Buffer.alloc(MAX_LENGTH);
2684
+ const bytesRead = fs10.readSync(fd, buffer, 0, MAX_LENGTH, 0);
2685
+ fs10.close(fd, () => {
2686
+ });
2687
+ return buffer.subarray(0, bytesRead);
2688
+ };
2689
+ var readFile2 = (path) => new Promise((resolve3, reject) => {
2690
+ fs10.open(path, "r", (err, fd) => {
2691
+ if (err) {
2692
+ reject(err);
2693
+ } else {
2694
+ const buffer = Buffer.alloc(MAX_LENGTH);
2695
+ fs10.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
2696
+ resolve3(buffer.subarray(0, bytesRead));
2697
+ fs10.close(fd, () => {
2698
+ });
2699
+ });
2700
+ }
2701
+ });
2702
+ });
2703
+ module2.exports = {
2704
+ LDD_PATH,
2705
+ SELF_PATH,
2706
+ readFileSync: readFileSync2,
2707
+ readFile: readFile2
2708
+ };
2709
+ }
2710
+ });
2711
+
2712
+ // ../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/elf.js
2713
+ var require_elf = __commonJS({
2714
+ "../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/elf.js"(exports, module2) {
2715
+ "use strict";
2716
+ var interpreterPath = (elf) => {
2717
+ if (elf.length < 64) {
2718
+ return null;
2719
+ }
2720
+ if (elf.readUInt32BE(0) !== 2135247942) {
2721
+ return null;
2722
+ }
2723
+ if (elf.readUInt8(4) !== 2) {
2724
+ return null;
2725
+ }
2726
+ if (elf.readUInt8(5) !== 1) {
2727
+ return null;
2728
+ }
2729
+ const offset = elf.readUInt32LE(32);
2730
+ const size = elf.readUInt16LE(54);
2731
+ const count = elf.readUInt16LE(56);
2732
+ for (let i = 0; i < count; i++) {
2733
+ const headerOffset = offset + i * size;
2734
+ const type = elf.readUInt32LE(headerOffset);
2735
+ if (type === 3) {
2736
+ const fileOffset = elf.readUInt32LE(headerOffset + 8);
2737
+ const fileSize = elf.readUInt32LE(headerOffset + 32);
2738
+ return elf.subarray(fileOffset, fileOffset + fileSize).toString().replace(/\0.*$/g, "");
2739
+ }
2740
+ }
2741
+ return null;
2742
+ };
2743
+ module2.exports = {
2744
+ interpreterPath
2745
+ };
2746
+ }
2747
+ });
2748
+
2749
+ // ../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/detect-libc.js
2750
+ var require_detect_libc = __commonJS({
2751
+ "../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/detect-libc.js"(exports, module2) {
2752
+ "use strict";
2753
+ var childProcess = require("child_process");
2754
+ var { isLinux, getReport } = require_process();
2755
+ var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync: readFileSync2 } = require_filesystem();
2756
+ var { interpreterPath } = require_elf();
2757
+ var cachedFamilyInterpreter;
2758
+ var cachedFamilyFilesystem;
2759
+ var cachedVersionFilesystem;
2760
+ var command = "getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true";
2761
+ var commandOut = "";
2762
+ var safeCommand = () => {
2763
+ if (!commandOut) {
2764
+ return new Promise((resolve3) => {
2765
+ childProcess.exec(command, (err, out) => {
2766
+ commandOut = err ? " " : out;
2767
+ resolve3(commandOut);
2768
+ });
2769
+ });
2770
+ }
2771
+ return commandOut;
2772
+ };
2773
+ var safeCommandSync = () => {
2774
+ if (!commandOut) {
2775
+ try {
2776
+ commandOut = childProcess.execSync(command, { encoding: "utf8" });
2777
+ } catch (_err) {
2778
+ commandOut = " ";
2779
+ }
2780
+ }
2781
+ return commandOut;
2782
+ };
2783
+ var GLIBC2 = "glibc";
2784
+ var RE_GLIBC_VERSION = /LIBC[a-z0-9 \-).]*?(\d+\.\d+)/i;
2785
+ var MUSL2 = "musl";
2786
+ var isFileMusl = (f) => f.includes("libc.musl-") || f.includes("ld-musl-");
2787
+ var familyFromReport = () => {
2788
+ const report = getReport();
2789
+ if (report.header && report.header.glibcVersionRuntime) {
2790
+ return GLIBC2;
2791
+ }
2792
+ if (Array.isArray(report.sharedObjects)) {
2793
+ if (report.sharedObjects.some(isFileMusl)) {
2794
+ return MUSL2;
2795
+ }
2796
+ }
2797
+ return null;
2798
+ };
2799
+ var familyFromCommand = (out) => {
2800
+ const [getconf, ldd1] = out.split(/[\r\n]+/);
2801
+ if (getconf && getconf.includes(GLIBC2)) {
2802
+ return GLIBC2;
2803
+ }
2804
+ if (ldd1 && ldd1.includes(MUSL2)) {
2805
+ return MUSL2;
2806
+ }
2807
+ return null;
2808
+ };
2809
+ var familyFromInterpreterPath = (path) => {
2810
+ if (path) {
2811
+ if (path.includes("/ld-musl-")) {
2812
+ return MUSL2;
2813
+ } else if (path.includes("/ld-linux-")) {
2814
+ return GLIBC2;
2815
+ }
2816
+ }
2817
+ return null;
2818
+ };
2819
+ var getFamilyFromLddContent = (content) => {
2820
+ content = content.toString();
2821
+ if (content.includes("musl")) {
2822
+ return MUSL2;
2823
+ }
2824
+ if (content.includes("GNU C Library")) {
2825
+ return GLIBC2;
2826
+ }
2827
+ return null;
2828
+ };
2829
+ var familyFromFilesystem = async () => {
2830
+ if (cachedFamilyFilesystem !== void 0) {
2831
+ return cachedFamilyFilesystem;
2832
+ }
2833
+ cachedFamilyFilesystem = null;
2834
+ try {
2835
+ const lddContent = await readFile2(LDD_PATH);
2836
+ cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
2837
+ } catch (e) {
2838
+ }
2839
+ return cachedFamilyFilesystem;
2840
+ };
2841
+ var familyFromFilesystemSync = () => {
2842
+ if (cachedFamilyFilesystem !== void 0) {
2843
+ return cachedFamilyFilesystem;
2844
+ }
2845
+ cachedFamilyFilesystem = null;
2846
+ try {
2847
+ const lddContent = readFileSync2(LDD_PATH);
2848
+ cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
2849
+ } catch (e) {
2850
+ }
2851
+ return cachedFamilyFilesystem;
2852
+ };
2853
+ var familyFromInterpreter = async () => {
2854
+ if (cachedFamilyInterpreter !== void 0) {
2855
+ return cachedFamilyInterpreter;
2856
+ }
2857
+ cachedFamilyInterpreter = null;
2858
+ try {
2859
+ const selfContent = await readFile2(SELF_PATH);
2860
+ const path = interpreterPath(selfContent);
2861
+ cachedFamilyInterpreter = familyFromInterpreterPath(path);
2862
+ } catch (e) {
2863
+ }
2864
+ return cachedFamilyInterpreter;
2865
+ };
2866
+ var familyFromInterpreterSync = () => {
2867
+ if (cachedFamilyInterpreter !== void 0) {
2868
+ return cachedFamilyInterpreter;
2869
+ }
2870
+ cachedFamilyInterpreter = null;
2871
+ try {
2872
+ const selfContent = readFileSync2(SELF_PATH);
2873
+ const path = interpreterPath(selfContent);
2874
+ cachedFamilyInterpreter = familyFromInterpreterPath(path);
2875
+ } catch (e) {
2876
+ }
2877
+ return cachedFamilyInterpreter;
2878
+ };
2879
+ var family = async () => {
2880
+ let family2 = null;
2881
+ if (isLinux()) {
2882
+ family2 = await familyFromInterpreter();
2883
+ if (!family2) {
2884
+ family2 = await familyFromFilesystem();
2885
+ if (!family2) {
2886
+ family2 = familyFromReport();
2887
+ }
2888
+ if (!family2) {
2889
+ const out = await safeCommand();
2890
+ family2 = familyFromCommand(out);
2891
+ }
2892
+ }
2893
+ }
2894
+ return family2;
2895
+ };
2896
+ var familySync2 = () => {
2897
+ let family2 = null;
2898
+ if (isLinux()) {
2899
+ family2 = familyFromInterpreterSync();
2900
+ if (!family2) {
2901
+ family2 = familyFromFilesystemSync();
2902
+ if (!family2) {
2903
+ family2 = familyFromReport();
2904
+ }
2905
+ if (!family2) {
2906
+ const out = safeCommandSync();
2907
+ family2 = familyFromCommand(out);
2908
+ }
2909
+ }
2910
+ }
2911
+ return family2;
2912
+ };
2913
+ var isNonGlibcLinux = async () => isLinux() && await family() !== GLIBC2;
2914
+ var isNonGlibcLinuxSync = () => isLinux() && familySync2() !== GLIBC2;
2915
+ var versionFromFilesystem = async () => {
2916
+ if (cachedVersionFilesystem !== void 0) {
2917
+ return cachedVersionFilesystem;
2918
+ }
2919
+ cachedVersionFilesystem = null;
2920
+ try {
2921
+ const lddContent = await readFile2(LDD_PATH);
2922
+ const versionMatch = lddContent.match(RE_GLIBC_VERSION);
2923
+ if (versionMatch) {
2924
+ cachedVersionFilesystem = versionMatch[1];
2925
+ }
2926
+ } catch (e) {
2927
+ }
2928
+ return cachedVersionFilesystem;
2929
+ };
2930
+ var versionFromFilesystemSync = () => {
2931
+ if (cachedVersionFilesystem !== void 0) {
2932
+ return cachedVersionFilesystem;
2933
+ }
2934
+ cachedVersionFilesystem = null;
2935
+ try {
2936
+ const lddContent = readFileSync2(LDD_PATH);
2937
+ const versionMatch = lddContent.match(RE_GLIBC_VERSION);
2938
+ if (versionMatch) {
2939
+ cachedVersionFilesystem = versionMatch[1];
2940
+ }
2941
+ } catch (e) {
2942
+ }
2943
+ return cachedVersionFilesystem;
2944
+ };
2945
+ var versionFromReport = () => {
2946
+ const report = getReport();
2947
+ if (report.header && report.header.glibcVersionRuntime) {
2948
+ return report.header.glibcVersionRuntime;
2949
+ }
2950
+ return null;
2951
+ };
2952
+ var versionSuffix = (s) => s.trim().split(/\s+/)[1];
2953
+ var versionFromCommand = (out) => {
2954
+ const [getconf, ldd1, ldd2] = out.split(/[\r\n]+/);
2955
+ if (getconf && getconf.includes(GLIBC2)) {
2956
+ return versionSuffix(getconf);
2957
+ }
2958
+ if (ldd1 && ldd2 && ldd1.includes(MUSL2)) {
2959
+ return versionSuffix(ldd2);
2960
+ }
2961
+ return null;
2962
+ };
2963
+ var version2 = async () => {
2964
+ let version3 = null;
2965
+ if (isLinux()) {
2966
+ version3 = await versionFromFilesystem();
2967
+ if (!version3) {
2968
+ version3 = versionFromReport();
2969
+ }
2970
+ if (!version3) {
2971
+ const out = await safeCommand();
2972
+ version3 = versionFromCommand(out);
2973
+ }
2974
+ }
2975
+ return version3;
2976
+ };
2977
+ var versionSync2 = () => {
2978
+ let version3 = null;
2979
+ if (isLinux()) {
2980
+ version3 = versionFromFilesystemSync();
2981
+ if (!version3) {
2982
+ version3 = versionFromReport();
2983
+ }
2984
+ if (!version3) {
2985
+ const out = safeCommandSync();
2986
+ version3 = versionFromCommand(out);
2987
+ }
2988
+ }
2989
+ return version3;
2990
+ };
2991
+ module2.exports = {
2992
+ GLIBC: GLIBC2,
2993
+ MUSL: MUSL2,
2994
+ family,
2995
+ familySync: familySync2,
2996
+ isNonGlibcLinux,
2997
+ isNonGlibcLinuxSync,
2998
+ version: version2,
2999
+ versionSync: versionSync2
3000
+ };
3001
+ }
3002
+ });
3003
+
2650
3004
  // ../../node_modules/.pnpm/which@3.0.0/node_modules/which/lib/index.js
2651
3005
  var require_lib = __commonJS({
2652
3006
  "../../node_modules/.pnpm/which@3.0.0/node_modules/which/lib/index.js"(exports, module2) {
@@ -2872,7 +3226,7 @@ var import_fs10 = __toESM(require("fs"));
2872
3226
  var import_path12 = require("path");
2873
3227
 
2874
3228
  // src/package-versions.ts
2875
- var VERCEL_RUNTIME_VERSION = "0.7.0";
3229
+ var VERCEL_RUNTIME_VERSION = "0.9.0";
2876
3230
  var VERCEL_WORKERS_VERSION = "0.0.12";
2877
3231
 
2878
3232
  // src/index.ts
@@ -2887,8 +3241,10 @@ var import_python_analysis2 = require("@vercel/python-analysis");
2887
3241
 
2888
3242
  // src/utils.ts
2889
3243
  var import_fs2 = __toESM(require("fs"));
3244
+ var import_os2 = __toESM(require("os"));
2890
3245
  var import_path3 = require("path");
2891
3246
  var import_build_utils2 = require("@vercel/build-utils");
3247
+ var detectLibc = __toESM(require_detect_libc());
2892
3248
  var import_execa2 = __toESM(require_execa());
2893
3249
 
2894
3250
  // src/uv.ts
@@ -3269,6 +3625,41 @@ async function runPyprojectScript(workPath, scriptNames, env, useUserVirtualEnv
3269
3625
  }
3270
3626
  return false;
3271
3627
  }
3628
+ var ARCH_MAP = {
3629
+ x64: "x86_64",
3630
+ arm64: "aarch64",
3631
+ ia32: "i686",
3632
+ arm: "armv7l",
3633
+ ppc64: "ppc64le",
3634
+ s390x: "s390x"
3635
+ };
3636
+ function detectPlatform() {
3637
+ const arch = import_os2.default.arch();
3638
+ const archName = ARCH_MAP[arch] || arch;
3639
+ const libcFamily = detectLibc.familySync();
3640
+ const libcVersion = detectLibc.versionSync();
3641
+ let osName;
3642
+ let osMajor;
3643
+ let osMinor;
3644
+ if (libcFamily === detectLibc.MUSL) {
3645
+ osName = "musllinux";
3646
+ } else {
3647
+ osName = "manylinux";
3648
+ }
3649
+ if (libcVersion) {
3650
+ const parts = libcVersion.split(".");
3651
+ osMajor = parseInt(parts[0], 10);
3652
+ osMinor = parseInt(parts[1], 10) || 0;
3653
+ } else if (libcFamily === detectLibc.GLIBC) {
3654
+ osMajor = 2;
3655
+ osMinor = 17;
3656
+ } else {
3657
+ osMajor = 2;
3658
+ osMinor = 17;
3659
+ }
3660
+ const libc = libcFamily === detectLibc.MUSL ? "musl" : "gnu";
3661
+ return { osName, archName, osMajor, osMinor, os: "linux", libc };
3662
+ }
3272
3663
 
3273
3664
  // src/version.ts
3274
3665
  var import_path4 = require("path");
@@ -3340,13 +3731,14 @@ function versionLessOrEqual(a, b) {
3340
3731
  return a.minor <= b.minor;
3341
3732
  }
3342
3733
  function toPythonBuild(opt) {
3734
+ const platform = detectPlatform();
3343
3735
  return {
3344
3736
  version: { major: opt.major, minor: opt.minor },
3345
3737
  implementation: "cpython",
3346
3738
  variant: "default",
3347
- os: "linux",
3348
- architecture: "x86_64",
3349
- libc: "gnu"
3739
+ os: platform.os,
3740
+ architecture: platform.archName,
3741
+ libc: platform.libc
3350
3742
  };
3351
3743
  }
3352
3744
  function getAvailablePythonBuilds() {
@@ -3817,8 +4209,7 @@ var import_path6 = require("path");
3817
4209
  var import_build_utils5 = require("@vercel/build-utils");
3818
4210
  var import_python_analysis3 = require("@vercel/python-analysis");
3819
4211
  var readFile = (0, import_util.promisify)(import_fs4.default.readFile);
3820
- var LAMBDA_SIZE_THRESHOLD_BYTES = 249 * 1024 * 1024;
3821
- var LAMBDA_PACKING_TARGET_BYTES = 240 * 1024 * 1024;
4212
+ var LAMBDA_SIZE_THRESHOLD_BYTES = 245 * 1024 * 1024;
3822
4213
  var LAMBDA_EPHEMERAL_STORAGE_BYTES = 500 * 1024 * 1024;
3823
4214
  var PythonDependencyExternalizer = class {
3824
4215
  constructor(options) {
@@ -3832,7 +4223,8 @@ var PythonDependencyExternalizer = class {
3832
4223
  this.uvLockPath = options.uvLockPath;
3833
4224
  this.uvProjectDir = options.uvProjectDir;
3834
4225
  this.projectName = options.projectName;
3835
- this.noBuildCheckFailed = options.noBuildCheckFailed;
4226
+ this.pythonMajor = options.pythonMajor;
4227
+ this.pythonMinor = options.pythonMinor;
3836
4228
  this.pythonPath = options.pythonPath;
3837
4229
  this.hasCustomCommand = options.hasCustomCommand;
3838
4230
  this.alwaysBundlePackages = options.alwaysBundlePackages ?? [];
@@ -3921,17 +4313,6 @@ To resolve this, either:
3921
4313
  action: "Learn More"
3922
4314
  });
3923
4315
  }
3924
- if (this.noBuildCheckFailed) {
3925
- throw new import_build_utils5.NowBuildError({
3926
- code: "RUNTIME_DEPENDENCY_INSTALLATION_FAILED",
3927
- message: `Bundle size exceeds the Lambda limit and requires runtime dependency installation, but some packages in your uv.lock file do not have pre-built binary wheels available.
3928
- Runtime dependency installation requires all public packages to have binary wheels.
3929
-
3930
- To fix this, either:
3931
- 1. Regenerate your lock file with: uv lock --upgrade --no-build, or
3932
- 2. Switch the problematic packages to ones that have pre-built wheels available`
3933
- });
3934
- }
3935
4316
  let lockContent;
3936
4317
  try {
3937
4318
  lockContent = await readFile(this.uvLockPath, "utf8");
@@ -3982,10 +4363,30 @@ ${error.fileContent}`
3982
4363
  (0, import_build_utils5.debug)(
3983
4364
  `Package classification: ${classification.privatePackages.length} private, ${classification.publicPackages.length} public`
3984
4365
  );
3985
- if (classification.publicPackages.length === 0) {
4366
+ const forceBundledDueToWheels = await this.findPackagesWithoutCompatibleWheels(
4367
+ lockFile,
4368
+ classification.publicPackages
4369
+ );
4370
+ if (forceBundledDueToWheels.length > 0) {
4371
+ console.log(
4372
+ `Force-bundling ${forceBundledDueToWheels.length} package(s) without compatible wheels: ` + forceBundledDueToWheels.join(", ")
4373
+ );
4374
+ }
4375
+ const forceBundledSet = new Set(
4376
+ forceBundledDueToWheels.map(import_python_analysis3.normalizePackageName)
4377
+ );
4378
+ const externalizablePublic = classification.publicPackages.filter(
4379
+ (name) => !forceBundledSet.has((0, import_python_analysis3.normalizePackageName)(name))
4380
+ );
4381
+ if (externalizablePublic.length === 0) {
3986
4382
  throw new import_build_utils5.NowBuildError({
3987
4383
  code: "RUNTIME_DEPENDENCY_INSTALLATION_FAILED",
3988
- message: "Bundle size exceeds limit but no public packages found for runtime installation."
4384
+ message: `Bundle size exceeds the Lambda limit and requires runtime dependency installation, but no public packages have compatible pre-built wheels for the Lambda platform.
4385
+ Runtime dependency installation requires packages to have binary wheels.
4386
+
4387
+ To fix this, either:
4388
+ 1. Regenerate your lock file with: uv lock --upgrade, or
4389
+ 2. Switch the problematic packages to ones that have pre-built wheels available`
3989
4390
  });
3990
4391
  }
3991
4392
  const packageSizes = await calculatePerPackageSizes(this.venvPath);
@@ -3993,7 +4394,8 @@ ${error.fileContent}`
3993
4394
  ...classification.privatePackages,
3994
4395
  "vercel-runtime",
3995
4396
  "vercel_runtime",
3996
- ...this.alwaysBundlePackages
4397
+ ...this.alwaysBundlePackages,
4398
+ ...forceBundledDueToWheels
3997
4399
  ];
3998
4400
  const alwaysBundledFiles = await mirrorPackagesIntoVendor({
3999
4401
  venvPath: this.venvPath,
@@ -4015,13 +4417,16 @@ ${error.fileContent}`
4015
4417
  runtimeToolingOverhead = 50 * 1024 * 1024;
4016
4418
  }
4017
4419
  }
4018
- const remainingCapacity = LAMBDA_PACKING_TARGET_BYTES - fixedOverhead - runtimeToolingOverhead;
4420
+ const remainingCapacity = LAMBDA_SIZE_THRESHOLD_BYTES - fixedOverhead - runtimeToolingOverhead;
4019
4421
  (0, import_build_utils5.debug)(
4020
4422
  `Fixed overhead: ${(fixedOverhead / (1024 * 1024)).toFixed(2)} MB, runtime tooling: ${(runtimeToolingOverhead / (1024 * 1024)).toFixed(2)} MB, remaining capacity for public packages: ${(remainingCapacity / (1024 * 1024)).toFixed(2)} MB`
4021
4423
  );
4424
+ const externalizableSet = new Set(
4425
+ externalizablePublic.map(import_python_analysis3.normalizePackageName)
4426
+ );
4022
4427
  const publicPackageSizes = new Map(
4023
4428
  [...packageSizes].filter(
4024
- ([name]) => classification.publicPackages.includes(name)
4429
+ ([name]) => externalizableSet.has((0, import_python_analysis3.normalizePackageName)(name))
4025
4430
  )
4026
4431
  );
4027
4432
  const bundledPublic = lambdaKnapsack(publicPackageSizes, remainingCapacity);
@@ -4037,7 +4442,8 @@ ${error.fileContent}`
4037
4442
  const bundledPackagesForConfig = [
4038
4443
  ...classification.privatePackages,
4039
4444
  ...bundledPublic,
4040
- ...this.alwaysBundlePackages
4445
+ ...this.alwaysBundlePackages,
4446
+ ...forceBundledDueToWheels
4041
4447
  ];
4042
4448
  const projectDirRel = (0, import_path6.relative)(this.workPath, this.uvProjectDir);
4043
4449
  const uvLockRel = (0, import_path6.relative)(this.workPath, this.uvLockPath);
@@ -4092,6 +4498,60 @@ ${error.fileContent}`
4092
4498
  });
4093
4499
  }
4094
4500
  }
4501
+ /**
4502
+ * Identify public packages that have no compatible wheel for the Lambda platform.
4503
+ * These packages must be force-bundled because `uv sync --no-build` at cold start
4504
+ * will refuse to build from source.
4505
+ */
4506
+ async findPackagesWithoutCompatibleWheels(lockFile, publicPackageNames) {
4507
+ const platform = detectPlatform();
4508
+ const publicSet = new Set(publicPackageNames.map(import_python_analysis3.normalizePackageName));
4509
+ const packageWheels = /* @__PURE__ */ new Map();
4510
+ for (const pkg of lockFile.packages) {
4511
+ const normalized = (0, import_python_analysis3.normalizePackageName)(pkg.name);
4512
+ if (publicSet.has(normalized) && pkg.wheels.length > 0) {
4513
+ packageWheels.set(normalized, pkg.wheels);
4514
+ }
4515
+ }
4516
+ const incompatible = [];
4517
+ for (const name of publicPackageNames) {
4518
+ const normalized = (0, import_python_analysis3.normalizePackageName)(name);
4519
+ const wheels = packageWheels.get(normalized);
4520
+ if (!wheels || wheels.length === 0) {
4521
+ incompatible.push(name);
4522
+ continue;
4523
+ }
4524
+ let hasCompatible = false;
4525
+ for (const wheel of wheels) {
4526
+ const filename = wheel.url.split("/").pop();
4527
+ if (!filename || !filename.endsWith(".whl"))
4528
+ continue;
4529
+ try {
4530
+ const compatible = await (0, import_python_analysis3.isWheelCompatible)(
4531
+ filename,
4532
+ this.pythonMajor,
4533
+ this.pythonMinor,
4534
+ platform.osName,
4535
+ platform.archName,
4536
+ platform.osMajor,
4537
+ platform.osMinor
4538
+ );
4539
+ if (compatible) {
4540
+ hasCompatible = true;
4541
+ break;
4542
+ }
4543
+ } catch (err) {
4544
+ (0, import_build_utils5.debug)(
4545
+ `Failed to check wheel compatibility for ${filename}: ${err instanceof Error ? err.message : String(err)}`
4546
+ );
4547
+ }
4548
+ }
4549
+ if (!hasCompatible) {
4550
+ incompatible.push(name);
4551
+ }
4552
+ }
4553
+ return incompatible;
4554
+ }
4095
4555
  };
4096
4556
  async function mirrorPackagesIntoVendor({
4097
4557
  venvPath,
@@ -4349,7 +4809,7 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint)
4349
4809
 
4350
4810
  // src/start-dev-server.ts
4351
4811
  var import_python_analysis4 = require("@vercel/python-analysis");
4352
- var DEV_SERVER_STARTUP_TIMEOUT = 1e4;
4812
+ var DEV_SERVER_STARTUP_TIMEOUT = 5 * 6e4;
4353
4813
  function silenceNodeWarnings() {
4354
4814
  const original = process.emitWarning.bind(
4355
4815
  process
@@ -4555,6 +5015,7 @@ async function runSync({
4555
5015
  });
4556
5016
  });
4557
5017
  }
5018
+ var PENDING_RUNTIME_INSTALLS = /* @__PURE__ */ new Map();
4558
5019
  async function installVercelRuntime({
4559
5020
  workPath,
4560
5021
  uvPath,
@@ -4564,6 +5025,31 @@ async function installVercelRuntime({
4564
5025
  onStderr
4565
5026
  }) {
4566
5027
  const targetDir = (0, import_path8.join)(workPath, ".vercel", "python");
5028
+ let pending = PENDING_RUNTIME_INSTALLS.get(targetDir);
5029
+ if (!pending) {
5030
+ pending = doInstallVercelRuntime({
5031
+ targetDir,
5032
+ workPath,
5033
+ uvPath,
5034
+ pythonBin,
5035
+ env,
5036
+ onStdout,
5037
+ onStderr
5038
+ });
5039
+ PENDING_RUNTIME_INSTALLS.set(targetDir, pending);
5040
+ pending.finally(() => PENDING_RUNTIME_INSTALLS.delete(targetDir));
5041
+ }
5042
+ await pending;
5043
+ }
5044
+ async function doInstallVercelRuntime({
5045
+ targetDir,
5046
+ workPath,
5047
+ uvPath,
5048
+ pythonBin,
5049
+ env,
5050
+ onStdout,
5051
+ onStderr
5052
+ }) {
4567
5053
  (0, import_fs6.mkdirSync)(targetDir, { recursive: true });
4568
5054
  const localRuntimeDir = (0, import_path8.join)(
4569
5055
  __dirname,
@@ -4667,9 +5153,9 @@ function installGlobalCleanupHandlers() {
4667
5153
  killAll();
4668
5154
  });
4669
5155
  }
4670
- function createDevShim(workPath, entry, modulePath) {
5156
+ function createDevShim(workPath, entry, modulePath, serviceName, framework) {
4671
5157
  try {
4672
- const vercelPythonDir = (0, import_path8.join)(workPath, ".vercel", "python");
5158
+ const vercelPythonDir = serviceName ? (0, import_path8.join)(workPath, ".vercel", "python", "services", serviceName) : (0, import_path8.join)(workPath, ".vercel", "python");
4673
5159
  (0, import_fs6.mkdirSync)(vercelPythonDir, { recursive: true });
4674
5160
  let qualifiedModule = modulePath;
4675
5161
  let extraPythonPath;
@@ -4687,10 +5173,14 @@ function createDevShim(workPath, entry, modulePath) {
4687
5173
  `${DEV_SHIM_MODULE}.py`
4688
5174
  );
4689
5175
  const template = (0, import_fs6.readFileSync)(templatePath, "utf8");
4690
- const shimSource = template.replace(/__VC_DEV_MODULE_NAME__/g, qualifiedModule).replace(/__VC_DEV_ENTRY_ABS__/g, entryAbs);
5176
+ const shimSource = template.replace(/__VC_DEV_MODULE_NAME__/g, qualifiedModule).replace(/__VC_DEV_ENTRY_ABS__/g, entryAbs).replace(/__VC_DEV_FRAMEWORK__/g, framework);
4691
5177
  (0, import_fs6.writeFileSync)(shimPath, shimSource, "utf8");
4692
5178
  (0, import_build_utils8.debug)(`Prepared Python dev shim at ${shimPath}`);
4693
- return { module: DEV_SHIM_MODULE, extraPythonPath };
5179
+ return {
5180
+ module: DEV_SHIM_MODULE,
5181
+ extraPythonPath,
5182
+ shimDir: vercelPythonDir
5183
+ };
4694
5184
  } catch (err) {
4695
5185
  (0, import_build_utils8.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
4696
5186
  return null;
@@ -4721,7 +5211,8 @@ var startDevServer = async (opts) => {
4721
5211
  onStderr
4722
5212
  } = opts;
4723
5213
  const framework = config?.framework;
4724
- const serverKey = `${workPath}::${framework}`;
5214
+ const serviceName = typeof meta.serviceName === "string" ? meta.serviceName : void 0;
5215
+ const serverKey = serviceName ? `${workPath}::${framework}::${serviceName}` : `${workPath}::${framework}`;
4725
5216
  const existing = PERSISTENT_SERVERS.get(serverKey);
4726
5217
  if (existing) {
4727
5218
  return {
@@ -4749,30 +5240,37 @@ var startDevServer = async (opts) => {
4749
5240
  if (!restoreWarnings)
4750
5241
  restoreWarnings = silenceNodeWarnings();
4751
5242
  installGlobalCleanupHandlers();
4752
- const detected = await detectPythonEntrypoint(
4753
- framework,
4754
- workPath,
4755
- rawEntrypoint
4756
- );
4757
5243
  const env = { ...process.env, ...meta.env || {} };
4758
- let entry = detected?.entrypoint;
4759
- if (!entry) {
4760
- const hookResult = await runFrameworkHook(framework, {
4761
- pythonEnv: env,
4762
- projectDir: (0, import_path8.join)(workPath, detected?.baseDir ?? ""),
4763
- entrypoint: rawEntrypoint,
4764
- detected: detected ?? void 0
4765
- });
4766
- entry = hookResult?.entrypoint;
4767
- }
4768
- if (!entry) {
4769
- const searched = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
4770
- throw new import_build_utils8.NowBuildError({
4771
- code: "PYTHON_ENTRYPOINT_NOT_FOUND",
4772
- message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searched}.`,
4773
- link: `https://vercel.com/docs/frameworks/backend/${framework?.toLowerCase()}#exporting-the-${framework?.toLowerCase()}-application`,
4774
- action: "Learn More"
4775
- });
5244
+ const serviceType = env.VERCEL_SERVICE_TYPE;
5245
+ let entry;
5246
+ if ((serviceType === "cron" || serviceType === "worker") && rawEntrypoint?.endsWith(".py")) {
5247
+ entry = rawEntrypoint;
5248
+ } else {
5249
+ const detected = await detectPythonEntrypoint(
5250
+ framework,
5251
+ workPath,
5252
+ rawEntrypoint
5253
+ );
5254
+ entry = detected?.entrypoint;
5255
+ if (!entry) {
5256
+ const hookResult = await runFrameworkHook(framework, {
5257
+ pythonEnv: env,
5258
+ projectDir: (0, import_path8.join)(workPath, detected?.baseDir ?? ""),
5259
+ workPath,
5260
+ entrypoint: rawEntrypoint,
5261
+ detected: detected ?? void 0
5262
+ });
5263
+ entry = hookResult?.entrypoint;
5264
+ }
5265
+ if (!entry) {
5266
+ const searched = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
5267
+ throw new import_build_utils8.NowBuildError({
5268
+ code: "PYTHON_ENTRYPOINT_NOT_FOUND",
5269
+ message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searched}.`,
5270
+ link: `https://vercel.com/docs/frameworks/backend/${framework?.toLowerCase()}#exporting-the-${framework?.toLowerCase()}-application`,
5271
+ action: "Learn More"
5272
+ });
5273
+ }
4776
5274
  }
4777
5275
  const modulePath = entry.replace(/\.py$/i, "").replace(/[\\/]/g, ".");
4778
5276
  let childProcess = null;
@@ -4870,10 +5368,23 @@ If you are using a virtual environment, activate it before running "vercel dev",
4870
5368
  });
4871
5369
  const port = typeof meta.port === "number" ? meta.port : await (0, import_get_port.default)();
4872
5370
  env.PORT = `${port}`;
4873
- const devShim = createDevShim(workPath, entry, modulePath);
5371
+ if (config.handlerFunction && typeof config?.handlerFunction === "string") {
5372
+ env.__VC_HANDLER_FUNC_NAME = config.handlerFunction;
5373
+ }
5374
+ if (entry) {
5375
+ env.__VC_HANDLER_ENTRYPOINT_ABS = (0, import_path8.join)(workPath, entry);
5376
+ }
5377
+ const devShim = createDevShim(
5378
+ workPath,
5379
+ entry,
5380
+ modulePath,
5381
+ serviceName,
5382
+ framework
5383
+ );
4874
5384
  if (devShim) {
4875
- const vercelPythonDir = (0, import_path8.join)(workPath, ".vercel", "python");
4876
- const pathParts = [vercelPythonDir];
5385
+ const shimDir = devShim.shimDir || (0, import_path8.join)(workPath, ".vercel", "python");
5386
+ const runtimeDir = (0, import_path8.join)(workPath, ".vercel", "python");
5387
+ const pathParts = shimDir !== runtimeDir ? [shimDir, runtimeDir] : [shimDir];
4877
5388
  if (devShim.extraPythonPath) {
4878
5389
  pathParts.push(devShim.extraPythonPath);
4879
5390
  }
@@ -5034,7 +5545,8 @@ var DUMMY_SCHEMA_NAME = "_prisma_dummy.prisma";
5034
5545
  var LAMBDA_ROOT2 = "/var/task";
5035
5546
  var RUNTIME_OPENSSL_VERSION = "3.2";
5036
5547
  function getLambdaBinaryTarget() {
5037
- return process.arch === "arm64" ? "linux-arm64-openssl-3.0.x" : "rhel-openssl-3.0.x";
5548
+ const platform = detectPlatform();
5549
+ return platform.archName === "aarch64" ? "linux-arm64-openssl-3.0.x" : "rhel-openssl-3.0.x";
5038
5550
  }
5039
5551
  function buildDummySchema(generatedDir) {
5040
5552
  const lambdaTarget = getLambdaBinaryTarget();
@@ -5547,15 +6059,18 @@ var frameworkHooks = {
5547
6059
  (0, import_build_utils13.debug)(`Django hook: WSGI entrypoint: ${entrypoint}`);
5548
6060
  }
5549
6061
  }
5550
- const outputStaticDir = (0, import_path12.join)(workPath, ".vercel", "output", "static");
5551
- const djangoStatic = await runDjangoCollectStatic(
5552
- venvPath,
5553
- workPath,
5554
- pythonEnv,
5555
- outputStaticDir,
5556
- settingsModule,
5557
- djangoSettings
5558
- );
6062
+ let djangoStatic = null;
6063
+ if (venvPath) {
6064
+ const outputStaticDir = (0, import_path12.join)(workPath, ".vercel", "output", "static");
6065
+ djangoStatic = await runDjangoCollectStatic(
6066
+ venvPath,
6067
+ workPath,
6068
+ pythonEnv,
6069
+ outputStaticDir,
6070
+ settingsModule,
6071
+ djangoSettings
6072
+ );
6073
+ }
5559
6074
  return { entrypoint, djangoStatic };
5560
6075
  }
5561
6076
  };
@@ -5717,7 +6232,6 @@ var build = async ({
5717
6232
  let uvLockPath = null;
5718
6233
  let uvProjectDir = null;
5719
6234
  let projectName;
5720
- let noBuildCheckFailed = false;
5721
6235
  await builderSpan.child(import_build_utils13.BUILDER_INSTALLER_STEP, {
5722
6236
  installCommand: projectInstallCommand || void 0
5723
6237
  }).trace(async () => {
@@ -5756,22 +6270,6 @@ var build = async ({
5756
6270
  uvLockPath = lockPath;
5757
6271
  uvProjectDir = projectDir;
5758
6272
  projectName = pythonPackage?.manifest?.data?.project?.name;
5759
- if (lockFileProvidedByUser) {
5760
- try {
5761
- await uv.sync({
5762
- venvPath,
5763
- projectDir,
5764
- frozen: true,
5765
- noBuild: true,
5766
- noInstallProject: true
5767
- });
5768
- } catch (err) {
5769
- noBuildCheckFailed = true;
5770
- (0, import_build_utils13.debug)(
5771
- `--no-build check failed: ${err instanceof Error ? err.message : String(err)}`
5772
- );
5773
- }
5774
- }
5775
6273
  await uv.sync({
5776
6274
  venvPath,
5777
6275
  projectDir,
@@ -5945,7 +6443,8 @@ from vercel_runtime.vc_init import vc_handler
5945
6443
  uvLockPath,
5946
6444
  uvProjectDir,
5947
6445
  projectName,
5948
- noBuildCheckFailed,
6446
+ pythonMajor: pythonVersion.major,
6447
+ pythonMinor: pythonVersion.minor,
5949
6448
  pythonPath: pythonVersion.pythonPath,
5950
6449
  hasCustomCommand,
5951
6450
  alwaysBundlePackages: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "6.23.0",
3
+ "version": "6.24.0",
4
4
  "main": "./dist/index.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -15,7 +15,7 @@
15
15
  "directory": "packages/python"
16
16
  },
17
17
  "dependencies": {
18
- "@vercel/python-analysis": "0.9.1"
18
+ "@vercel/python-analysis": "0.10.0"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@renovatebot/pep440": "4.2.1",
@@ -25,19 +25,20 @@
25
25
  "@types/node": "20.11.0",
26
26
  "@types/which": "3.0.0",
27
27
  "cross-env": "7.0.3",
28
+ "detect-libc": "2.1.2",
28
29
  "execa": "^1.0.0",
29
30
  "fs-extra": "11.1.1",
31
+ "get-port": "5.1.1",
32
+ "is-port-reachable": "3.1.0",
30
33
  "jest-junit": "16.0.0",
31
34
  "minimatch": "10.1.1",
32
35
  "pip-requirements-js": "1.0.2",
33
36
  "smol-toml": "1.5.2",
34
37
  "vitest": "2.1.4",
35
38
  "which": "3.0.0",
36
- "get-port": "5.1.1",
37
- "is-port-reachable": "3.1.0",
38
- "@vercel/build-utils": "13.8.0",
39
39
  "@vercel/error-utils": "2.0.3",
40
- "@vercel/python-runtime": "0.7.0"
40
+ "@vercel/python-runtime": "0.9.0",
41
+ "@vercel/build-utils": "13.8.1"
41
42
  },
42
43
  "scripts": {
43
44
  "build": "node ../../utils/build-builder.mjs",
@@ -6,6 +6,7 @@ os.environ.update(
6
6
  {
7
7
  "VERCEL_DEV_MODULE_NAME": "__VC_DEV_MODULE_NAME__",
8
8
  "VERCEL_DEV_ENTRY_ABS": "__VC_DEV_ENTRY_ABS__",
9
+ "VERCEL_DEV_FRAMEWORK": "__VC_DEV_FRAMEWORK__",
9
10
  }
10
11
  )
11
12