@vercel/python 6.1.0 → 6.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +624 -503
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -48,7 +48,7 @@ var require_windows = __commonJS({
48
48
  "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/windows.js"(exports, module2) {
49
49
  module2.exports = isexe;
50
50
  isexe.sync = sync;
51
- var fs6 = require("fs");
51
+ var fs5 = require("fs");
52
52
  function checkPathExt(path, options) {
53
53
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
54
54
  if (!pathext) {
@@ -73,12 +73,12 @@ var require_windows = __commonJS({
73
73
  return checkPathExt(path, options);
74
74
  }
75
75
  function isexe(path, options, cb) {
76
- fs6.stat(path, function(er, stat) {
76
+ fs5.stat(path, function(er, stat) {
77
77
  cb(er, er ? false : checkStat(stat, path, options));
78
78
  });
79
79
  }
80
80
  function sync(path, options) {
81
- return checkStat(fs6.statSync(path), path, options);
81
+ return checkStat(fs5.statSync(path), path, options);
82
82
  }
83
83
  }
84
84
  });
@@ -88,14 +88,14 @@ var require_mode = __commonJS({
88
88
  "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/mode.js"(exports, module2) {
89
89
  module2.exports = isexe;
90
90
  isexe.sync = sync;
91
- var fs6 = require("fs");
91
+ var fs5 = require("fs");
92
92
  function isexe(path, options, cb) {
93
- fs6.stat(path, function(er, stat) {
93
+ fs5.stat(path, function(er, stat) {
94
94
  cb(er, er ? false : checkStat(stat, options));
95
95
  });
96
96
  }
97
97
  function sync(path, options) {
98
- return checkStat(fs6.statSync(path), options);
98
+ return checkStat(fs5.statSync(path), options);
99
99
  }
100
100
  function checkStat(stat, options) {
101
101
  return stat.isFile() && checkMode(stat, options);
@@ -119,7 +119,7 @@ var require_mode = __commonJS({
119
119
  // ../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js
120
120
  var require_isexe = __commonJS({
121
121
  "../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module2) {
122
- var fs6 = require("fs");
122
+ var fs5 = require("fs");
123
123
  var core;
124
124
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
125
125
  core = require_windows();
@@ -395,7 +395,7 @@ var require_shebang_command = __commonJS({
395
395
  var require_readShebang = __commonJS({
396
396
  "../../node_modules/.pnpm/cross-spawn@6.0.5/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module2) {
397
397
  "use strict";
398
- var fs6 = require("fs");
398
+ var fs5 = require("fs");
399
399
  var shebangCommand = require_shebang_command();
400
400
  function readShebang(command) {
401
401
  const size = 150;
@@ -408,9 +408,9 @@ var require_readShebang = __commonJS({
408
408
  }
409
409
  let fd;
410
410
  try {
411
- fd = fs6.openSync(command, "r");
412
- fs6.readSync(fd, buffer, 0, size, 0);
413
- fs6.closeSync(fd);
411
+ fd = fs5.openSync(command, "r");
412
+ fs5.readSync(fd, buffer, 0, size, 0);
413
+ fs5.closeSync(fd);
414
414
  } catch (e) {
415
415
  }
416
416
  return shebangCommand(buffer.toString());
@@ -1498,7 +1498,7 @@ var require_parse = __commonJS({
1498
1498
  var escape = require_escape();
1499
1499
  var readShebang = require_readShebang();
1500
1500
  var semver = require_semver();
1501
- var isWin2 = process.platform === "win32";
1501
+ var isWin3 = process.platform === "win32";
1502
1502
  var isExecutableRegExp = /\.(?:com|exe)$/i;
1503
1503
  var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
1504
1504
  var supportsShellOption = niceTry(() => semver.satisfies(process.version, "^4.8.0 || ^5.7.0 || >= 6.0.0", true)) || false;
@@ -1513,7 +1513,7 @@ var require_parse = __commonJS({
1513
1513
  return parsed.file;
1514
1514
  }
1515
1515
  function parseNonShell(parsed) {
1516
- if (!isWin2) {
1516
+ if (!isWin3) {
1517
1517
  return parsed;
1518
1518
  }
1519
1519
  const commandFile = detectShebang(parsed);
@@ -1535,7 +1535,7 @@ var require_parse = __commonJS({
1535
1535
  return parsed;
1536
1536
  }
1537
1537
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
1538
- if (isWin2) {
1538
+ if (isWin3) {
1539
1539
  parsed.command = typeof parsed.options.shell === "string" ? parsed.options.shell : process.env.comspec || "cmd.exe";
1540
1540
  parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
1541
1541
  parsed.options.windowsVerbatimArguments = true;
@@ -1578,7 +1578,7 @@ var require_parse = __commonJS({
1578
1578
  var require_enoent = __commonJS({
1579
1579
  "../../node_modules/.pnpm/cross-spawn@6.0.5/node_modules/cross-spawn/lib/enoent.js"(exports, module2) {
1580
1580
  "use strict";
1581
- var isWin2 = process.platform === "win32";
1581
+ var isWin3 = process.platform === "win32";
1582
1582
  function notFoundError(original, syscall) {
1583
1583
  return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
1584
1584
  code: "ENOENT",
@@ -1589,7 +1589,7 @@ var require_enoent = __commonJS({
1589
1589
  });
1590
1590
  }
1591
1591
  function hookChildProcess(cp, parsed) {
1592
- if (!isWin2) {
1592
+ if (!isWin3) {
1593
1593
  return;
1594
1594
  }
1595
1595
  const originalEmit = cp.emit;
@@ -1604,13 +1604,13 @@ var require_enoent = __commonJS({
1604
1604
  };
1605
1605
  }
1606
1606
  function verifyENOENT(status, parsed) {
1607
- if (isWin2 && status === 1 && !parsed.file) {
1607
+ if (isWin3 && status === 1 && !parsed.file) {
1608
1608
  return notFoundError(parsed.original, "spawn");
1609
1609
  }
1610
1610
  return null;
1611
1611
  }
1612
1612
  function verifyENOENTSync(status, parsed) {
1613
- if (isWin2 && status === 1 && !parsed.file) {
1613
+ if (isWin3 && status === 1 && !parsed.file) {
1614
1614
  return notFoundError(parsed.original, "spawnSync");
1615
1615
  }
1616
1616
  return null;
@@ -1895,9 +1895,9 @@ var require_pump = __commonJS({
1895
1895
  "../../node_modules/.pnpm/pump@3.0.2/node_modules/pump/index.js"(exports, module2) {
1896
1896
  var once = require_once();
1897
1897
  var eos = require_end_of_stream();
1898
- var fs6;
1898
+ var fs5;
1899
1899
  try {
1900
- fs6 = require("fs");
1900
+ fs5 = require("fs");
1901
1901
  } catch (e) {
1902
1902
  }
1903
1903
  var noop = function() {
@@ -1909,9 +1909,9 @@ var require_pump = __commonJS({
1909
1909
  var isFS = function(stream) {
1910
1910
  if (!ancient)
1911
1911
  return false;
1912
- if (!fs6)
1912
+ if (!fs5)
1913
1913
  return false;
1914
- return (stream instanceof (fs6.ReadStream || noop) || stream instanceof (fs6.WriteStream || noop)) && isFn(stream.close);
1914
+ return (stream instanceof (fs5.ReadStream || noop) || stream instanceof (fs5.WriteStream || noop)) && isFn(stream.close);
1915
1915
  };
1916
1916
  var isRequest = function(stream) {
1917
1917
  return stream.setHeader && isFn(stream.abort);
@@ -2143,7 +2143,7 @@ var require_signal_exit = __commonJS({
2143
2143
  } else {
2144
2144
  assert = require("assert");
2145
2145
  signals = require_signals();
2146
- isWin2 = /^win/i.test(process2.platform);
2146
+ isWin3 = /^win/i.test(process2.platform);
2147
2147
  EE = require("events");
2148
2148
  if (typeof EE !== "function") {
2149
2149
  EE = EE.EventEmitter;
@@ -2215,7 +2215,7 @@ var require_signal_exit = __commonJS({
2215
2215
  unload();
2216
2216
  emit("exit", null, sig);
2217
2217
  emit("afterexit", null, sig);
2218
- if (isWin2 && sig === "SIGHUP") {
2218
+ if (isWin3 && sig === "SIGHUP") {
2219
2219
  sig = "SIGINT";
2220
2220
  }
2221
2221
  process2.kill(process2.pid, sig);
@@ -2272,7 +2272,7 @@ var require_signal_exit = __commonJS({
2272
2272
  }
2273
2273
  var assert;
2274
2274
  var signals;
2275
- var isWin2;
2275
+ var isWin3;
2276
2276
  var EE;
2277
2277
  var emitter;
2278
2278
  var unload;
@@ -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: join7, delimiter, sep, posix } = require("path");
2654
+ var { join: join6, delimiter, sep, posix } = require("path");
2655
2655
  var isWindows = process.platform === "win32";
2656
2656
  var rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? "" : sep}]`.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 + join7(pathPart, cmd);
2683
+ return prefix + join6(pathPart, cmd);
2684
2684
  };
2685
2685
  var which3 = async (cmd, opt = {}) => {
2686
2686
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -2748,20 +2748,139 @@ __export(src_exports, {
2748
2748
  version: () => version
2749
2749
  });
2750
2750
  module.exports = __toCommonJS(src_exports);
2751
- var import_fs6 = __toESM(require("fs"));
2751
+ var import_fs5 = __toESM(require("fs"));
2752
2752
  var import_util = require("util");
2753
- var import_path6 = require("path");
2754
- var import_build_utils8 = require("@vercel/build-utils");
2753
+ var import_path5 = require("path");
2754
+ var import_build_utils7 = require("@vercel/build-utils");
2755
2755
 
2756
2756
  // src/install.ts
2757
2757
  var import_execa = __toESM(require_execa());
2758
- var import_fs = __toESM(require("fs"));
2758
+ var import_fs2 = __toESM(require("fs"));
2759
2759
  var import_os = __toESM(require("os"));
2760
- var import_path = require("path");
2760
+ var import_path2 = require("path");
2761
2761
  var import_which = __toESM(require_lib());
2762
+ var import_build_utils2 = require("@vercel/build-utils");
2763
+
2764
+ // src/utils.ts
2765
+ var import_fs = __toESM(require("fs"));
2766
+ var import_path = require("path");
2762
2767
  var import_build_utils = require("@vercel/build-utils");
2768
+ var execa = require_execa();
2763
2769
  var isWin = process.platform === "win32";
2764
- var uvExec = isWin ? "uv.exe" : "uv";
2770
+ var isInVirtualEnv = () => {
2771
+ return process.env.VIRTUAL_ENV;
2772
+ };
2773
+ function getVenvBinDir(venvPath) {
2774
+ return (0, import_path.join)(venvPath, isWin ? "Scripts" : "bin");
2775
+ }
2776
+ function useVirtualEnv(workPath, env, systemPython) {
2777
+ const venvDirs = [".venv", "venv"];
2778
+ let pythonCmd = systemPython;
2779
+ for (const venv of venvDirs) {
2780
+ const venvRoot = (0, import_path.join)(workPath, venv);
2781
+ const binDir = process.platform === "win32" ? (0, import_path.join)(venvRoot, "Scripts") : (0, import_path.join)(venvRoot, "bin");
2782
+ const candidates = process.platform === "win32" ? [(0, import_path.join)(binDir, "python.exe"), (0, import_path.join)(binDir, "python")] : [(0, import_path.join)(binDir, "python3"), (0, import_path.join)(binDir, "python")];
2783
+ const found = candidates.find((p) => import_fs.default.existsSync(p));
2784
+ if (found) {
2785
+ pythonCmd = found;
2786
+ env.VIRTUAL_ENV = venvRoot;
2787
+ env.PATH = `${binDir}${import_path.delimiter}${env.PATH || ""}`;
2788
+ return { pythonCmd, venvRoot };
2789
+ }
2790
+ }
2791
+ return { pythonCmd };
2792
+ }
2793
+ function createVenvEnv(venvPath, baseEnv = process.env) {
2794
+ const env = { ...baseEnv, VIRTUAL_ENV: venvPath };
2795
+ const binDir = getVenvBinDir(venvPath);
2796
+ const existingPath = env.PATH || process.env.PATH || "";
2797
+ env.PATH = existingPath ? `${binDir}${import_path.delimiter}${existingPath}` : binDir;
2798
+ return env;
2799
+ }
2800
+ async function ensureVenv({
2801
+ pythonPath,
2802
+ venvPath
2803
+ }) {
2804
+ const marker = (0, import_path.join)(venvPath, "pyvenv.cfg");
2805
+ try {
2806
+ await import_fs.default.promises.access(marker);
2807
+ return;
2808
+ } catch {
2809
+ }
2810
+ await import_fs.default.promises.mkdir(venvPath, { recursive: true });
2811
+ console.log(`Creating virtual environment at "${venvPath}"...`);
2812
+ await execa(pythonPath, ["-m", "venv", venvPath]);
2813
+ }
2814
+ function getVenvPythonBin(venvPath) {
2815
+ return (0, import_path.join)(getVenvBinDir(venvPath), isWin ? "python.exe" : "python");
2816
+ }
2817
+ async function runPyprojectScript(workPath, scriptNames, env) {
2818
+ const pyprojectPath = (0, import_path.join)(workPath, "pyproject.toml");
2819
+ if (!import_fs.default.existsSync(pyprojectPath))
2820
+ return false;
2821
+ let pyproject = null;
2822
+ try {
2823
+ pyproject = await (0, import_build_utils.readConfigFile)(pyprojectPath);
2824
+ } catch {
2825
+ console.error("Failed to parse pyproject.toml");
2826
+ return false;
2827
+ }
2828
+ const scripts = pyproject?.tool?.vercel?.scripts || {};
2829
+ const candidates = typeof scriptNames === "string" ? [scriptNames] : Array.from(scriptNames);
2830
+ const scriptToRun = candidates.find((name) => Boolean(scripts[name]));
2831
+ if (!scriptToRun)
2832
+ return false;
2833
+ const systemPython = process.platform === "win32" ? "python" : "python3";
2834
+ const finalEnv = { ...process.env, ...env };
2835
+ useVirtualEnv(workPath, finalEnv, systemPython);
2836
+ const scriptCommand = scripts[scriptToRun];
2837
+ if (typeof scriptCommand === "string" && scriptCommand.trim()) {
2838
+ console.log(`Executing: ${scriptCommand}`);
2839
+ await (0, import_build_utils.execCommand)(scriptCommand, {
2840
+ cwd: workPath,
2841
+ env: finalEnv
2842
+ });
2843
+ return true;
2844
+ }
2845
+ return false;
2846
+ }
2847
+ async function runUvCommand(options) {
2848
+ const { uvPath, args, cwd, venvPath } = options;
2849
+ const pretty = `uv ${args.join(" ")}`;
2850
+ (0, import_build_utils.debug)(`Running "${pretty}"...`);
2851
+ if (!uvPath) {
2852
+ throw new Error(`uv is required to run "${pretty}" but is not available`);
2853
+ }
2854
+ try {
2855
+ await execa(uvPath, args, {
2856
+ cwd,
2857
+ env: createVenvEnv(venvPath)
2858
+ });
2859
+ return true;
2860
+ } catch (err) {
2861
+ throw new Error(
2862
+ `Failed to run "${pretty}": ${err instanceof Error ? err.message : String(err)}`
2863
+ );
2864
+ }
2865
+ }
2866
+ function findDir({
2867
+ file,
2868
+ entryDirectory,
2869
+ workPath,
2870
+ fsFiles
2871
+ }) {
2872
+ if (fsFiles[(0, import_path.join)(entryDirectory, file)]) {
2873
+ return (0, import_path.join)(workPath, entryDirectory);
2874
+ }
2875
+ if (fsFiles[file]) {
2876
+ return workPath;
2877
+ }
2878
+ return null;
2879
+ }
2880
+
2881
+ // src/install.ts
2882
+ var isWin2 = process.platform === "win32";
2883
+ var uvExec = isWin2 ? "uv.exe" : "uv";
2765
2884
  var makeDependencyCheckCode = (dependency) => `
2766
2885
  from importlib import util
2767
2886
  dep = '${dependency}'.replace('-', '_')
@@ -2776,7 +2895,7 @@ async function isInstalled(pythonPath, dependency, cwd) {
2776
2895
  {
2777
2896
  stdio: "pipe",
2778
2897
  cwd,
2779
- env: { ...process.env, PYTHONPATH: (0, import_path.join)(cwd, resolveVendorDir()) }
2898
+ env: { ...process.env, PYTHONPATH: (0, import_path2.join)(cwd, resolveVendorDir()) }
2780
2899
  }
2781
2900
  );
2782
2901
  return stdout.startsWith(cwd);
@@ -2799,7 +2918,7 @@ async function areRequirementsInstalled(pythonPath, requirementsPath, cwd) {
2799
2918
  {
2800
2919
  stdio: "pipe",
2801
2920
  cwd,
2802
- env: { ...process.env, PYTHONPATH: (0, import_path.join)(cwd, resolveVendorDir()) }
2921
+ env: { ...process.env, PYTHONPATH: (0, import_path2.join)(cwd, resolveVendorDir()) }
2803
2922
  }
2804
2923
  );
2805
2924
  return true;
@@ -2807,10 +2926,334 @@ async function areRequirementsInstalled(pythonPath, requirementsPath, cwd) {
2807
2926
  return false;
2808
2927
  }
2809
2928
  }
2929
+ async function runUvSync({
2930
+ uvPath,
2931
+ venvPath,
2932
+ projectDir,
2933
+ locked
2934
+ }) {
2935
+ const args = ["sync", "--active", "--no-dev"];
2936
+ if (locked) {
2937
+ args.push("--locked");
2938
+ }
2939
+ args.push("--no-editable");
2940
+ await runUvCommand({
2941
+ uvPath,
2942
+ args,
2943
+ cwd: projectDir,
2944
+ venvPath
2945
+ });
2946
+ }
2947
+ async function getSitePackagesDirs(pythonBin) {
2948
+ const code = `
2949
+ import json
2950
+ import sysconfig
2951
+ paths = []
2952
+ for key in ("purelib", "platlib"):
2953
+ candidate = sysconfig.get_path(key)
2954
+ if candidate and candidate not in paths:
2955
+ paths.append(candidate)
2956
+ print(json.dumps(paths))
2957
+ `.trim();
2958
+ const { stdout } = await (0, import_execa.default)(pythonBin, ["-c", code]);
2959
+ try {
2960
+ const parsed = JSON.parse(stdout);
2961
+ if (Array.isArray(parsed)) {
2962
+ return parsed.filter((p) => typeof p === "string");
2963
+ }
2964
+ } catch (err) {
2965
+ (0, import_build_utils2.debug)("Failed to parse site-packages output", err);
2966
+ }
2967
+ return [];
2968
+ }
2969
+ async function getVenvSitePackagesDirs(venvPath) {
2970
+ const pythonBin = getVenvPythonBin(venvPath);
2971
+ return getSitePackagesDirs(pythonBin);
2972
+ }
2810
2973
  function resolveVendorDir() {
2811
2974
  const vendorDir = process.env.VERCEL_PYTHON_VENDOR_DIR || "_vendor";
2812
2975
  return vendorDir;
2813
2976
  }
2977
+ async function detectInstallSource({
2978
+ workPath,
2979
+ entryDirectory,
2980
+ fsFiles
2981
+ }) {
2982
+ const uvLockDir = findDir({
2983
+ file: "uv.lock",
2984
+ entryDirectory,
2985
+ workPath,
2986
+ fsFiles
2987
+ });
2988
+ const pyprojectDir = findDir({
2989
+ file: "pyproject.toml",
2990
+ entryDirectory,
2991
+ workPath,
2992
+ fsFiles
2993
+ });
2994
+ const pipfileLockDir = findDir({
2995
+ file: "Pipfile.lock",
2996
+ entryDirectory,
2997
+ workPath,
2998
+ fsFiles
2999
+ });
3000
+ const pipfileDir = findDir({
3001
+ file: "Pipfile",
3002
+ entryDirectory,
3003
+ workPath,
3004
+ fsFiles
3005
+ });
3006
+ const requirementsDir = findDir({
3007
+ file: "requirements.txt",
3008
+ entryDirectory,
3009
+ workPath,
3010
+ fsFiles
3011
+ });
3012
+ let manifestPath = null;
3013
+ let manifestType = null;
3014
+ if (uvLockDir && pyprojectDir) {
3015
+ manifestType = "uv.lock";
3016
+ manifestPath = (0, import_path2.join)(uvLockDir, "uv.lock");
3017
+ } else if (pyprojectDir) {
3018
+ manifestType = "pyproject.toml";
3019
+ manifestPath = (0, import_path2.join)(pyprojectDir, "pyproject.toml");
3020
+ } else if (pipfileLockDir) {
3021
+ manifestType = "Pipfile.lock";
3022
+ manifestPath = (0, import_path2.join)(pipfileLockDir, "Pipfile.lock");
3023
+ } else if (pipfileDir) {
3024
+ manifestType = "Pipfile";
3025
+ manifestPath = (0, import_path2.join)(pipfileDir, "Pipfile");
3026
+ } else if (requirementsDir) {
3027
+ manifestType = "requirements.txt";
3028
+ manifestPath = (0, import_path2.join)(requirementsDir, "requirements.txt");
3029
+ }
3030
+ let manifestContent;
3031
+ if (manifestPath) {
3032
+ try {
3033
+ manifestContent = await import_fs2.default.promises.readFile(manifestPath, "utf8");
3034
+ } catch (err) {
3035
+ (0, import_build_utils2.debug)("Failed to read install manifest contents", err);
3036
+ }
3037
+ }
3038
+ return { manifestPath, manifestType, manifestContent };
3039
+ }
3040
+ async function createPyprojectToml({
3041
+ projectName,
3042
+ pyprojectPath,
3043
+ dependencies
3044
+ }) {
3045
+ const requiresPython = ">=3.12";
3046
+ const depsToml = dependencies.length > 0 ? [
3047
+ "dependencies = [",
3048
+ ...dependencies.map((dep) => ` "${dep}",`),
3049
+ "]"
3050
+ ].join("\n") : "dependencies = []";
3051
+ const content = [
3052
+ "[project]",
3053
+ `name = "${projectName}"`,
3054
+ 'version = "0.1.0"',
3055
+ `requires-python = "${requiresPython}"`,
3056
+ "classifiers = [",
3057
+ ' "Private :: Do Not Upload",',
3058
+ "]",
3059
+ depsToml,
3060
+ ""
3061
+ ].join("\n");
3062
+ await import_fs2.default.promises.writeFile(pyprojectPath, content);
3063
+ }
3064
+ async function uvLock({
3065
+ projectDir,
3066
+ uvPath
3067
+ }) {
3068
+ const args = ["lock"];
3069
+ const pretty = `${uvPath} ${args.join(" ")}`;
3070
+ (0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
3071
+ try {
3072
+ await (0, import_execa.default)(uvPath, args, { cwd: projectDir });
3073
+ } catch (err) {
3074
+ throw new Error(
3075
+ `Failed to run "${pretty}": ${err instanceof Error ? err.message : String(err)}`
3076
+ );
3077
+ }
3078
+ }
3079
+ async function uvAddDependencies({
3080
+ projectDir,
3081
+ uvPath,
3082
+ venvPath,
3083
+ dependencies
3084
+ }) {
3085
+ const toAdd = dependencies.filter(Boolean);
3086
+ if (!toAdd.length)
3087
+ return;
3088
+ const args = ["add", "--active", ...toAdd];
3089
+ const pretty = `${uvPath} ${args.join(" ")}`;
3090
+ (0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
3091
+ await runUvCommand({ uvPath, args, cwd: projectDir, venvPath });
3092
+ }
3093
+ async function uvAddFromFile({
3094
+ projectDir,
3095
+ uvPath,
3096
+ venvPath,
3097
+ requirementsPath
3098
+ }) {
3099
+ const args = ["add", "--active", "-r", requirementsPath];
3100
+ const pretty = `${uvPath} ${args.join(" ")}`;
3101
+ (0, import_build_utils2.debug)(`Running "${pretty}" in ${projectDir}...`);
3102
+ await runUvCommand({ uvPath, args, cwd: projectDir, venvPath });
3103
+ }
3104
+ function getDependencyName(spec) {
3105
+ const match = spec.match(/^[A-Za-z0-9_.-]+/);
3106
+ return match ? match[0].toLowerCase() : spec.toLowerCase();
3107
+ }
3108
+ async function filterMissingRuntimeDependencies({
3109
+ pyprojectPath,
3110
+ runtimeDependencies
3111
+ }) {
3112
+ let declared = [];
3113
+ try {
3114
+ const config = await (0, import_build_utils2.readConfigFile)(pyprojectPath);
3115
+ declared = config?.project?.dependencies || [];
3116
+ } catch (err) {
3117
+ (0, import_build_utils2.debug)("Failed to parse pyproject.toml when filtering runtime deps", err);
3118
+ }
3119
+ const declaredNames = new Set(declared.map(getDependencyName));
3120
+ return runtimeDependencies.filter((spec) => {
3121
+ const name = getDependencyName(spec);
3122
+ return !declaredNames.has(name);
3123
+ });
3124
+ }
3125
+ async function ensureUvProject({
3126
+ workPath,
3127
+ entryDirectory,
3128
+ fsFiles,
3129
+ pythonPath,
3130
+ pipPath,
3131
+ uvPath,
3132
+ venvPath,
3133
+ meta,
3134
+ runtimeDependencies
3135
+ }) {
3136
+ const installInfo = await detectInstallSource({
3137
+ workPath,
3138
+ entryDirectory,
3139
+ fsFiles
3140
+ });
3141
+ const { manifestType, manifestPath } = installInfo;
3142
+ let projectDir;
3143
+ let pyprojectPath;
3144
+ if (manifestType === "uv.lock") {
3145
+ if (!manifestPath) {
3146
+ throw new Error("Expected uv.lock path to be resolved, but it was null");
3147
+ }
3148
+ projectDir = (0, import_path2.dirname)(manifestPath);
3149
+ pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
3150
+ if (!import_fs2.default.existsSync(pyprojectPath)) {
3151
+ throw new Error(
3152
+ `Expected "pyproject.toml" next to "uv.lock" in "${projectDir}"`
3153
+ );
3154
+ }
3155
+ console.log("Installing required dependencies from uv.lock...");
3156
+ } else if (manifestType === "pyproject.toml") {
3157
+ if (!manifestPath) {
3158
+ throw new Error(
3159
+ "Expected pyproject.toml path to be resolved, but it was null"
3160
+ );
3161
+ }
3162
+ projectDir = (0, import_path2.dirname)(manifestPath);
3163
+ pyprojectPath = manifestPath;
3164
+ console.log("Installing required dependencies from pyproject.toml...");
3165
+ const lockPath2 = (0, import_path2.join)(projectDir, "uv.lock");
3166
+ if (!import_fs2.default.existsSync(lockPath2)) {
3167
+ await uvLock({ projectDir, uvPath });
3168
+ }
3169
+ } else if (manifestType === "Pipfile.lock" || manifestType === "Pipfile") {
3170
+ if (!manifestPath) {
3171
+ throw new Error(
3172
+ "Expected Pipfile/Pipfile.lock path to be resolved, but it was null"
3173
+ );
3174
+ }
3175
+ projectDir = (0, import_path2.dirname)(manifestPath);
3176
+ console.log(`Installing required dependencies from ${manifestType}...`);
3177
+ const exportedReq = await exportRequirementsFromPipfile({
3178
+ pythonPath,
3179
+ pipPath,
3180
+ uvPath,
3181
+ projectDir,
3182
+ meta
3183
+ });
3184
+ pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
3185
+ if (!import_fs2.default.existsSync(pyprojectPath)) {
3186
+ await createPyprojectToml({
3187
+ projectName: "app",
3188
+ pyprojectPath,
3189
+ dependencies: []
3190
+ });
3191
+ }
3192
+ await uvAddFromFile({
3193
+ projectDir,
3194
+ uvPath,
3195
+ venvPath,
3196
+ requirementsPath: exportedReq
3197
+ });
3198
+ } else if (manifestType === "requirements.txt") {
3199
+ if (!manifestPath) {
3200
+ throw new Error(
3201
+ "Expected requirements.txt path to be resolved, but it was null"
3202
+ );
3203
+ }
3204
+ projectDir = (0, import_path2.dirname)(manifestPath);
3205
+ pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
3206
+ console.log(
3207
+ "Installing required dependencies from requirements.txt with uv..."
3208
+ );
3209
+ if (!import_fs2.default.existsSync(pyprojectPath)) {
3210
+ await createPyprojectToml({
3211
+ projectName: "app",
3212
+ pyprojectPath,
3213
+ dependencies: []
3214
+ });
3215
+ }
3216
+ await uvAddFromFile({
3217
+ projectDir,
3218
+ uvPath,
3219
+ venvPath,
3220
+ requirementsPath: manifestPath
3221
+ });
3222
+ } else {
3223
+ projectDir = workPath;
3224
+ pyprojectPath = (0, import_path2.join)(projectDir, "pyproject.toml");
3225
+ console.log(
3226
+ "No Python manifest found; creating an empty pyproject.toml and uv.lock..."
3227
+ );
3228
+ await createPyprojectToml({
3229
+ projectName: "app",
3230
+ pyprojectPath,
3231
+ dependencies: []
3232
+ });
3233
+ await uvLock({ projectDir, uvPath });
3234
+ }
3235
+ if (runtimeDependencies.length) {
3236
+ const missingRuntimeDeps = await filterMissingRuntimeDependencies({
3237
+ pyprojectPath,
3238
+ runtimeDependencies
3239
+ });
3240
+ if (missingRuntimeDeps.length) {
3241
+ await uvAddDependencies({
3242
+ projectDir,
3243
+ uvPath,
3244
+ venvPath,
3245
+ dependencies: missingRuntimeDeps
3246
+ });
3247
+ }
3248
+ }
3249
+ const lockPath = (0, import_path2.join)(projectDir, "uv.lock");
3250
+ if (!import_fs2.default.existsSync(lockPath)) {
3251
+ throw new Error(
3252
+ `Expected "uv.lock" to exist in "${projectDir}" after preparing uv project`
3253
+ );
3254
+ }
3255
+ return { projectDir, pyprojectPath, lockPath };
3256
+ }
2814
3257
  async function getGlobalScriptsDir(pythonPath) {
2815
3258
  const code = `import sysconfig; print(sysconfig.get_path('scripts'))`;
2816
3259
  try {
@@ -2818,7 +3261,7 @@ async function getGlobalScriptsDir(pythonPath) {
2818
3261
  const out = stdout.trim();
2819
3262
  return out || null;
2820
3263
  } catch (err) {
2821
- (0, import_build_utils.debug)("Failed to resolve Python global scripts directory", err);
3264
+ (0, import_build_utils2.debug)("Failed to resolve Python global scripts directory", err);
2822
3265
  return null;
2823
3266
  }
2824
3267
  }
@@ -2832,12 +3275,12 @@ async function getUserScriptsDir(pythonPath) {
2832
3275
  const out = stdout.trim();
2833
3276
  return out || null;
2834
3277
  } catch (err) {
2835
- (0, import_build_utils.debug)("Failed to resolve Python user scripts directory", err);
3278
+ (0, import_build_utils2.debug)("Failed to resolve Python user scripts directory", err);
2836
3279
  return null;
2837
3280
  }
2838
3281
  }
2839
3282
  async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
2840
- const target = targetDir ? (0, import_path.join)(targetDir, resolveVendorDir()) : resolveVendorDir();
3283
+ const target = targetDir ? (0, import_path2.join)(targetDir, resolveVendorDir()) : resolveVendorDir();
2841
3284
  process.env.PIP_USER = "0";
2842
3285
  if (uvPath) {
2843
3286
  const uvArgs = [
@@ -2847,10 +3290,10 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
2847
3290
  "--no-cache-dir",
2848
3291
  "--target",
2849
3292
  target,
2850
- ...args
3293
+ ...filterUnsafeUvPipArgs(args)
2851
3294
  ];
2852
3295
  const prettyUv = `${uvPath} ${uvArgs.join(" ")}`;
2853
- (0, import_build_utils.debug)(`Running "${prettyUv}"...`);
3296
+ (0, import_build_utils2.debug)(`Running "${prettyUv}"...`);
2854
3297
  try {
2855
3298
  await (0, import_execa.default)(uvPath, uvArgs, {
2856
3299
  cwd: workPath
@@ -2858,7 +3301,7 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
2858
3301
  return;
2859
3302
  } catch (err) {
2860
3303
  console.log(`Failed to run "${prettyUv}", falling back to pip`);
2861
- (0, import_build_utils.debug)(`error: ${err}`);
3304
+ (0, import_build_utils2.debug)(`error: ${err}`);
2862
3305
  }
2863
3306
  }
2864
3307
  const cmdArgs = [
@@ -2871,14 +3314,14 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
2871
3314
  ...args
2872
3315
  ];
2873
3316
  const pretty = `${pipPath} ${cmdArgs.join(" ")}`;
2874
- (0, import_build_utils.debug)(`Running "${pretty}"...`);
3317
+ (0, import_build_utils2.debug)(`Running "${pretty}"...`);
2875
3318
  try {
2876
3319
  await (0, import_execa.default)(pipPath, cmdArgs, {
2877
3320
  cwd: workPath
2878
3321
  });
2879
3322
  } catch (err) {
2880
3323
  console.log(`Failed to run "${pretty}"`);
2881
- (0, import_build_utils.debug)(`error: ${err}`);
3324
+ (0, import_build_utils2.debug)(`error: ${err}`);
2882
3325
  throw err;
2883
3326
  }
2884
3327
  }
@@ -2889,38 +3332,38 @@ async function maybeFindUvBin(pythonPath) {
2889
3332
  try {
2890
3333
  const globalScriptsDir = await getGlobalScriptsDir(pythonPath);
2891
3334
  if (globalScriptsDir) {
2892
- const uvPath = (0, import_path.join)(globalScriptsDir, uvExec);
2893
- if (import_fs.default.existsSync(uvPath))
3335
+ const uvPath = (0, import_path2.join)(globalScriptsDir, uvExec);
3336
+ if (import_fs2.default.existsSync(uvPath))
2894
3337
  return uvPath;
2895
3338
  }
2896
3339
  } catch (err) {
2897
- (0, import_build_utils.debug)("Failed to resolve Python global scripts directory", err);
3340
+ (0, import_build_utils2.debug)("Failed to resolve Python global scripts directory", err);
2898
3341
  }
2899
3342
  try {
2900
3343
  const userScriptsDir = await getUserScriptsDir(pythonPath);
2901
3344
  if (userScriptsDir) {
2902
- const uvPath = (0, import_path.join)(userScriptsDir, uvExec);
2903
- if (import_fs.default.existsSync(uvPath))
3345
+ const uvPath = (0, import_path2.join)(userScriptsDir, uvExec);
3346
+ if (import_fs2.default.existsSync(uvPath))
2904
3347
  return uvPath;
2905
3348
  }
2906
3349
  } catch (err) {
2907
- (0, import_build_utils.debug)("Failed to resolve Python user scripts directory", err);
3350
+ (0, import_build_utils2.debug)("Failed to resolve Python user scripts directory", err);
2908
3351
  }
2909
3352
  try {
2910
3353
  const candidates = [];
2911
- if (!isWin) {
2912
- candidates.push((0, import_path.join)(import_os.default.homedir(), ".local", "bin", "uv"));
3354
+ if (!isWin2) {
3355
+ candidates.push((0, import_path2.join)(import_os.default.homedir(), ".local", "bin", "uv"));
2913
3356
  candidates.push("/usr/local/bin/uv");
2914
3357
  candidates.push("/opt/homebrew/bin/uv");
2915
3358
  } else {
2916
3359
  candidates.push("C:\\Users\\Public\\uv\\uv.exe");
2917
3360
  }
2918
3361
  for (const p of candidates) {
2919
- if (import_fs.default.existsSync(p))
3362
+ if (import_fs2.default.existsSync(p))
2920
3363
  return p;
2921
3364
  }
2922
3365
  } catch (err) {
2923
- (0, import_build_utils.debug)("Failed to resolve uv fallback paths", err);
3366
+ (0, import_build_utils2.debug)("Failed to resolve uv fallback paths", err);
2924
3367
  }
2925
3368
  return null;
2926
3369
  }
@@ -2968,7 +3411,7 @@ async function installRequirement({
2968
3411
  }) {
2969
3412
  const actualTargetDir = targetDir || workPath;
2970
3413
  if (meta.isDev && await isInstalled(pythonPath, dependency, actualTargetDir)) {
2971
- (0, import_build_utils.debug)(
3414
+ (0, import_build_utils2.debug)(
2972
3415
  `Skipping ${dependency} dependency installation, already installed in ${actualTargetDir}`
2973
3416
  );
2974
3417
  return;
@@ -2988,7 +3431,7 @@ async function installRequirementsFile({
2988
3431
  }) {
2989
3432
  const actualTargetDir = targetDir || workPath;
2990
3433
  if (meta.isDev && await areRequirementsInstalled(pythonPath, filePath, actualTargetDir)) {
2991
- (0, import_build_utils.debug)(`Skipping requirements file installation, already installed`);
3434
+ (0, import_build_utils2.debug)(`Skipping requirements file installation, already installed`);
2992
3435
  return;
2993
3436
  }
2994
3437
  await pipInstall(
@@ -2999,35 +3442,8 @@ async function installRequirementsFile({
2999
3442
  targetDir
3000
3443
  );
3001
3444
  }
3002
- async function exportRequirementsFromUv(projectDir, uvPath, options = {}) {
3003
- const { locked = false } = options;
3004
- if (!uvPath) {
3005
- throw new Error("uv is not available to export requirements");
3006
- }
3007
- const args = [
3008
- "export",
3009
- "--no-default-groups",
3010
- "--no-emit-workspace",
3011
- "--no-editable"
3012
- ];
3013
- if (locked) {
3014
- args.push("--frozen");
3015
- }
3016
- (0, import_build_utils.debug)(`Running "${uvPath} ${args.join(" ")}" in ${projectDir}...`);
3017
- let stdout;
3018
- try {
3019
- const { stdout: out } = await (0, import_execa.default)(uvPath, args, { cwd: projectDir });
3020
- stdout = out;
3021
- } catch (err) {
3022
- throw new Error(
3023
- `Failed to run "${uvPath} ${args.join(" ")}": ${err instanceof Error ? err.message : String(err)}`
3024
- );
3025
- }
3026
- const tmpDir = await import_fs.default.promises.mkdtemp((0, import_path.join)(import_os.default.tmpdir(), "vercel-uv-"));
3027
- const outPath = (0, import_path.join)(tmpDir, "requirements.uv.txt");
3028
- await import_fs.default.promises.writeFile(outPath, stdout);
3029
- (0, import_build_utils.debug)(`Exported requirements to ${outPath}`);
3030
- return outPath;
3445
+ function filterUnsafeUvPipArgs(args) {
3446
+ return args.filter((arg) => arg !== "--no-warn-script-location");
3031
3447
  }
3032
3448
  async function exportRequirementsFromPipfile({
3033
3449
  pythonPath,
@@ -3036,8 +3452,8 @@ async function exportRequirementsFromPipfile({
3036
3452
  projectDir,
3037
3453
  meta
3038
3454
  }) {
3039
- const tempDir = await import_fs.default.promises.mkdtemp(
3040
- (0, import_path.join)(import_os.default.tmpdir(), "vercel-pipenv-")
3455
+ const tempDir = await import_fs2.default.promises.mkdtemp(
3456
+ (0, import_path2.join)(import_os.default.tmpdir(), "vercel-pipenv-")
3041
3457
  );
3042
3458
  await installRequirement({
3043
3459
  pythonPath,
@@ -3049,9 +3465,9 @@ async function exportRequirementsFromPipfile({
3049
3465
  args: ["--no-warn-script-location"],
3050
3466
  uvPath
3051
3467
  });
3052
- const tempVendorDir = (0, import_path.join)(tempDir, resolveVendorDir());
3053
- const convertCmd = isWin ? (0, import_path.join)(tempVendorDir, "Scripts", "pipfile2req.exe") : (0, import_path.join)(tempVendorDir, "bin", "pipfile2req");
3054
- (0, import_build_utils.debug)(`Running "${convertCmd}" in ${projectDir}...`);
3468
+ const tempVendorDir = (0, import_path2.join)(tempDir, resolveVendorDir());
3469
+ const convertCmd = isWin2 ? (0, import_path2.join)(tempVendorDir, "Scripts", "pipfile2req.exe") : (0, import_path2.join)(tempVendorDir, "bin", "pipfile2req");
3470
+ (0, import_build_utils2.debug)(`Running "${convertCmd}" in ${projectDir}...`);
3055
3471
  let stdout;
3056
3472
  try {
3057
3473
  const { stdout: out } = await (0, import_execa.default)(convertCmd, [], {
@@ -3064,17 +3480,46 @@ async function exportRequirementsFromPipfile({
3064
3480
  `Failed to run "${convertCmd}": ${err instanceof Error ? err.message : String(err)}`
3065
3481
  );
3066
3482
  }
3067
- const outPath = (0, import_path.join)(tempDir, "requirements.pipenv.txt");
3068
- await import_fs.default.promises.writeFile(outPath, stdout);
3069
- (0, import_build_utils.debug)(`Exported pipfile requirements to ${outPath}`);
3483
+ const outPath = (0, import_path2.join)(tempDir, "requirements.pipenv.txt");
3484
+ await import_fs2.default.promises.writeFile(outPath, stdout);
3485
+ (0, import_build_utils2.debug)(`Exported pipfile requirements to ${outPath}`);
3070
3486
  return outPath;
3071
3487
  }
3488
+ async function mirrorSitePackagesIntoVendor({
3489
+ venvPath,
3490
+ vendorDirName
3491
+ }) {
3492
+ const vendorFiles = {};
3493
+ try {
3494
+ const sitePackageDirs = await getVenvSitePackagesDirs(venvPath);
3495
+ for (const dir of sitePackageDirs) {
3496
+ if (!import_fs2.default.existsSync(dir))
3497
+ continue;
3498
+ const dirFiles = await (0, import_build_utils2.glob)("**", dir);
3499
+ for (const relativePath of Object.keys(dirFiles)) {
3500
+ if (relativePath.endsWith(".pyc") || relativePath.includes("__pycache__")) {
3501
+ continue;
3502
+ }
3503
+ const srcFsPath = (0, import_path2.join)(dir, relativePath);
3504
+ const bundlePath = (0, import_path2.join)(vendorDirName, relativePath).replace(
3505
+ /\\/g,
3506
+ "/"
3507
+ );
3508
+ vendorFiles[bundlePath] = new import_build_utils2.FileFsRef({ fsPath: srcFsPath });
3509
+ }
3510
+ }
3511
+ } catch (err) {
3512
+ console.log("Failed to collect site-packages from virtual environment");
3513
+ throw err;
3514
+ }
3515
+ return vendorFiles;
3516
+ }
3072
3517
 
3073
3518
  // src/index.ts
3074
- var import_build_utils9 = require("@vercel/build-utils");
3519
+ var import_build_utils8 = require("@vercel/build-utils");
3075
3520
 
3076
3521
  // src/version.ts
3077
- var import_build_utils2 = require("@vercel/build-utils");
3522
+ var import_build_utils3 = require("@vercel/build-utils");
3078
3523
  var import_which2 = __toESM(require_lib());
3079
3524
  var allOptions = [
3080
3525
  {
@@ -3125,7 +3570,7 @@ function getLatestPythonVersion({
3125
3570
  }
3126
3571
  const selection = allOptions.find(isInstalled2);
3127
3572
  if (!selection) {
3128
- throw new import_build_utils2.NowBuildError({
3573
+ throw new import_build_utils3.NowBuildError({
3129
3574
  code: "PYTHON_NOT_FOUND",
3130
3575
  link: "http://vercel.link/python-version",
3131
3576
  message: `Unable to find any supported Python versions.`
@@ -3226,7 +3671,7 @@ function getSupportedPythonVersion({
3226
3671
  }
3227
3672
  if (requested) {
3228
3673
  if (isDiscontinued(requested)) {
3229
- throw new import_build_utils2.NowBuildError({
3674
+ throw new import_build_utils3.NowBuildError({
3230
3675
  code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
3231
3676
  link: "http://vercel.link/python-version",
3232
3677
  message: `Python version "${requested.version}" detected in ${source} is discontinued and must be upgraded.`
@@ -3257,7 +3702,7 @@ function getSupportedPythonVersion({
3257
3702
  );
3258
3703
  }
3259
3704
  if (isDiscontinued(selection)) {
3260
- throw new import_build_utils2.NowBuildError({
3705
+ throw new import_build_utils3.NowBuildError({
3261
3706
  code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
3262
3707
  link: "http://vercel.link/python-version",
3263
3708
  message: `Python version "${selection.version}" declared in project configuration is discontinued and must be upgraded.`
@@ -3287,16 +3732,16 @@ var import_path4 = require("path");
3287
3732
  var import_build_utils6 = require("@vercel/build-utils");
3288
3733
 
3289
3734
  // src/entrypoint.ts
3290
- var import_fs2 = __toESM(require("fs"));
3291
- var import_path2 = require("path");
3292
- var import_build_utils3 = require("@vercel/build-utils");
3735
+ var import_fs3 = __toESM(require("fs"));
3736
+ var import_path3 = require("path");
3293
3737
  var import_build_utils4 = require("@vercel/build-utils");
3738
+ var import_build_utils5 = require("@vercel/build-utils");
3294
3739
  var FASTAPI_ENTRYPOINT_FILENAMES = ["app", "index", "server", "main"];
3295
3740
  var FASTAPI_ENTRYPOINT_DIRS = ["", "src", "app", "api"];
3296
3741
  var FASTAPI_CONTENT_REGEX = /(from\s+fastapi\s+import\s+FastAPI|import\s+fastapi|FastAPI\s*\()/;
3297
3742
  var FASTAPI_CANDIDATE_ENTRYPOINTS = FASTAPI_ENTRYPOINT_FILENAMES.flatMap(
3298
3743
  (filename) => FASTAPI_ENTRYPOINT_DIRS.map(
3299
- (dir) => import_path2.posix.join(dir, `${filename}.py`)
3744
+ (dir) => import_path3.posix.join(dir, `${filename}.py`)
3300
3745
  )
3301
3746
  );
3302
3747
  function isFastapiEntrypoint(file) {
@@ -3304,7 +3749,7 @@ function isFastapiEntrypoint(file) {
3304
3749
  const fsPath = file.fsPath;
3305
3750
  if (!fsPath)
3306
3751
  return false;
3307
- const contents = import_fs2.default.readFileSync(fsPath, "utf8");
3752
+ const contents = import_fs3.default.readFileSync(fsPath, "utf8");
3308
3753
  return FASTAPI_CONTENT_REGEX.test(contents);
3309
3754
  } catch {
3310
3755
  return false;
@@ -3315,7 +3760,7 @@ var FLASK_ENTRYPOINT_DIRS = ["", "src", "app", "api"];
3315
3760
  var FLASK_CONTENT_REGEX = /(from\s+flask\s+import\s+Flask|import\s+flask|Flask\s*\()/;
3316
3761
  var FLASK_CANDIDATE_ENTRYPOINTS = FLASK_ENTRYPOINT_FILENAMES.flatMap(
3317
3762
  (filename) => FLASK_ENTRYPOINT_DIRS.map(
3318
- (dir) => import_path2.posix.join(dir, `${filename}.py`)
3763
+ (dir) => import_path3.posix.join(dir, `${filename}.py`)
3319
3764
  )
3320
3765
  );
3321
3766
  function isFlaskEntrypoint(file) {
@@ -3323,7 +3768,7 @@ function isFlaskEntrypoint(file) {
3323
3768
  const fsPath = file.fsPath;
3324
3769
  if (!fsPath)
3325
3770
  return false;
3326
- const contents = import_fs2.default.readFileSync(fsPath, "utf8");
3771
+ const contents = import_fs3.default.readFileSync(fsPath, "utf8");
3327
3772
  return FLASK_CONTENT_REGEX.test(contents);
3328
3773
  } catch {
3329
3774
  return false;
@@ -3332,7 +3777,7 @@ function isFlaskEntrypoint(file) {
3332
3777
  async function detectFlaskEntrypoint(workPath, configuredEntrypoint) {
3333
3778
  const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
3334
3779
  try {
3335
- const fsFiles = await (0, import_build_utils3.glob)("**", workPath);
3780
+ const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
3336
3781
  if (fsFiles[entry])
3337
3782
  return entry;
3338
3783
  const candidates = FLASK_CANDIDATE_ENTRYPOINTS.filter(
@@ -3342,19 +3787,19 @@ async function detectFlaskEntrypoint(workPath, configuredEntrypoint) {
3342
3787
  const flaskEntrypoint = candidates.find(
3343
3788
  (c) => isFlaskEntrypoint(fsFiles[c])
3344
3789
  ) || candidates[0];
3345
- (0, import_build_utils3.debug)(`Detected Flask entrypoint: ${flaskEntrypoint}`);
3790
+ (0, import_build_utils4.debug)(`Detected Flask entrypoint: ${flaskEntrypoint}`);
3346
3791
  return flaskEntrypoint;
3347
3792
  }
3348
3793
  return null;
3349
3794
  } catch {
3350
- (0, import_build_utils3.debug)("Failed to discover entrypoint for Flask");
3795
+ (0, import_build_utils4.debug)("Failed to discover entrypoint for Flask");
3351
3796
  return null;
3352
3797
  }
3353
3798
  }
3354
3799
  async function detectFastapiEntrypoint(workPath, configuredEntrypoint) {
3355
3800
  const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
3356
3801
  try {
3357
- const fsFiles = await (0, import_build_utils3.glob)("**", workPath);
3802
+ const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
3358
3803
  if (fsFiles[entry])
3359
3804
  return entry;
3360
3805
  const candidates = FASTAPI_CANDIDATE_ENTRYPOINTS.filter(
@@ -3364,17 +3809,17 @@ async function detectFastapiEntrypoint(workPath, configuredEntrypoint) {
3364
3809
  const fastapiEntrypoint = candidates.find(
3365
3810
  (c) => isFastapiEntrypoint(fsFiles[c])
3366
3811
  ) || candidates[0];
3367
- (0, import_build_utils3.debug)(`Detected FastAPI entrypoint: ${fastapiEntrypoint}`);
3812
+ (0, import_build_utils4.debug)(`Detected FastAPI entrypoint: ${fastapiEntrypoint}`);
3368
3813
  return fastapiEntrypoint;
3369
3814
  }
3370
3815
  return null;
3371
3816
  } catch {
3372
- (0, import_build_utils3.debug)("Failed to discover entrypoint for FastAPI");
3817
+ (0, import_build_utils4.debug)("Failed to discover entrypoint for FastAPI");
3373
3818
  return null;
3374
3819
  }
3375
3820
  }
3376
3821
  async function getPyprojectEntrypoint(workPath) {
3377
- const pyprojectData = await (0, import_build_utils4.readConfigFile)((0, import_path2.join)(workPath, "pyproject.toml"));
3822
+ const pyprojectData = await (0, import_build_utils5.readConfigFile)((0, import_path3.join)(workPath, "pyproject.toml"));
3378
3823
  if (!pyprojectData)
3379
3824
  return null;
3380
3825
  const scripts = pyprojectData.project?.scripts;
@@ -3387,7 +3832,7 @@ async function getPyprojectEntrypoint(workPath) {
3387
3832
  const modulePath = match[1];
3388
3833
  const relPath = modulePath.replace(/\./g, "/");
3389
3834
  try {
3390
- const fsFiles = await (0, import_build_utils3.glob)("**", workPath);
3835
+ const fsFiles = await (0, import_build_utils4.glob)("**", workPath);
3391
3836
  const candidates = [`${relPath}.py`, `${relPath}/__init__.py`];
3392
3837
  for (const candidate of candidates) {
3393
3838
  if (fsFiles[candidate])
@@ -3395,7 +3840,7 @@ async function getPyprojectEntrypoint(workPath) {
3395
3840
  }
3396
3841
  return null;
3397
3842
  } catch {
3398
- (0, import_build_utils3.debug)("Failed to discover Python entrypoint from pyproject.toml");
3843
+ (0, import_build_utils4.debug)("Failed to discover Python entrypoint from pyproject.toml");
3399
3844
  return null;
3400
3845
  }
3401
3846
  }
@@ -3411,61 +3856,6 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint)
3411
3856
  return await getPyprojectEntrypoint(workPath);
3412
3857
  }
3413
3858
 
3414
- // src/utils.ts
3415
- var import_fs3 = __toESM(require("fs"));
3416
- var import_path3 = require("path");
3417
- var import_build_utils5 = require("@vercel/build-utils");
3418
- var isInVirtualEnv = () => {
3419
- return process.env.VIRTUAL_ENV;
3420
- };
3421
- function useVirtualEnv(workPath, env, systemPython) {
3422
- const venvDirs = [".venv", "venv"];
3423
- let pythonCmd = systemPython;
3424
- for (const venv of venvDirs) {
3425
- const venvRoot = (0, import_path3.join)(workPath, venv);
3426
- const binDir = process.platform === "win32" ? (0, import_path3.join)(venvRoot, "Scripts") : (0, import_path3.join)(venvRoot, "bin");
3427
- const candidates = process.platform === "win32" ? [(0, import_path3.join)(binDir, "python.exe"), (0, import_path3.join)(binDir, "python")] : [(0, import_path3.join)(binDir, "python3"), (0, import_path3.join)(binDir, "python")];
3428
- const found = candidates.find((p) => import_fs3.default.existsSync(p));
3429
- if (found) {
3430
- pythonCmd = found;
3431
- env.VIRTUAL_ENV = venvRoot;
3432
- env.PATH = `${binDir}${import_path3.delimiter}${env.PATH || ""}`;
3433
- return { pythonCmd, venvRoot };
3434
- }
3435
- }
3436
- return { pythonCmd };
3437
- }
3438
- async function runPyprojectScript(workPath, scriptNames, env) {
3439
- const pyprojectPath = (0, import_path3.join)(workPath, "pyproject.toml");
3440
- if (!import_fs3.default.existsSync(pyprojectPath))
3441
- return false;
3442
- let pyproject = null;
3443
- try {
3444
- pyproject = await (0, import_build_utils5.readConfigFile)(pyprojectPath);
3445
- } catch {
3446
- console.error("Failed to parse pyproject.toml");
3447
- return false;
3448
- }
3449
- const scripts = pyproject?.tool?.vercel?.scripts || {};
3450
- const candidates = typeof scriptNames === "string" ? [scriptNames] : Array.from(scriptNames);
3451
- const scriptToRun = candidates.find((name) => Boolean(scripts[name]));
3452
- if (!scriptToRun)
3453
- return false;
3454
- const systemPython = process.platform === "win32" ? "python" : "python3";
3455
- const finalEnv = { ...process.env, ...env };
3456
- useVirtualEnv(workPath, finalEnv, systemPython);
3457
- const scriptCommand = scripts[scriptToRun];
3458
- if (typeof scriptCommand === "string" && scriptCommand.trim()) {
3459
- console.log(`Executing: ${scriptCommand}`);
3460
- await (0, import_build_utils5.execCommand)(scriptCommand, {
3461
- cwd: workPath,
3462
- env: finalEnv
3463
- });
3464
- return true;
3465
- }
3466
- return false;
3467
- }
3468
-
3469
3859
  // src/start-dev-server.ts
3470
3860
  function silenceNodeWarnings() {
3471
3861
  const original = process.emitWarning.bind(
@@ -3835,153 +4225,29 @@ If you are using a virtual environment, activate it before running "vercel dev",
3835
4225
  }
3836
4226
  };
3837
4227
 
3838
- // src/uv-workspace.ts
3839
- var import_fs5 = __toESM(require("fs"));
3840
- var import_os2 = __toESM(require("os"));
3841
- var import_path5 = require("path");
3842
- var import_build_utils7 = require("@vercel/build-utils");
3843
- function getDependencyName(spec) {
3844
- const match = spec.match(/^[A-Za-z0-9_.-]+/);
3845
- return match ? match[0] : null;
3846
- }
3847
- async function installUvWorkspaceDependencies({
3848
- repoRootPath,
3849
- pyprojectDir,
3850
- pythonPath,
3851
- pipPath,
3852
- uvPath,
3853
- workPath,
3854
- vendorBaseDir,
3855
- meta
3856
- }) {
3857
- if (!repoRootPath || !pyprojectDir) {
3858
- return;
3859
- }
3860
- let rootPyproject = null;
3861
- try {
3862
- rootPyproject = await (0, import_build_utils7.readConfigFile)(
3863
- (0, import_path5.join)(repoRootPath, "pyproject.toml")
3864
- );
3865
- } catch (err) {
3866
- (0, import_build_utils7.debug)("Failed to parse workspace root pyproject.toml", err);
3867
- }
3868
- const uvTool = rootPyproject?.tool?.uv;
3869
- const workspaceCfg = uvTool?.workspace;
3870
- const sourcesCfg = uvTool?.sources;
3871
- if (!workspaceCfg || !sourcesCfg) {
3872
- return;
3873
- }
3874
- const workspaceSourceNames = new Set(
3875
- Object.entries(sourcesCfg).filter(([, src]) => src && src.workspace).map(([name]) => name)
3876
- );
3877
- if (!workspaceSourceNames.size) {
3878
- return;
3879
- }
3880
- let appPyproject = null;
3881
- try {
3882
- appPyproject = await (0, import_build_utils7.readConfigFile)(
3883
- (0, import_path5.join)(pyprojectDir, "pyproject.toml")
3884
- );
3885
- } catch (err) {
3886
- (0, import_build_utils7.debug)("Failed to parse app pyproject.toml for workspace deps", err);
3887
- }
3888
- const appDeps = appPyproject?.project?.dependencies ?? [];
3889
- const workspaceDepsForApp = /* @__PURE__ */ new Set();
3890
- for (const spec of appDeps) {
3891
- const name = getDependencyName(spec);
3892
- if (name && workspaceSourceNames.has(name)) {
3893
- workspaceDepsForApp.add(name);
3894
- }
3895
- }
3896
- if (!workspaceDepsForApp.size) {
3897
- return;
3898
- }
3899
- const members = workspaceCfg.members ?? [];
3900
- const nameToDir = /* @__PURE__ */ new Map();
3901
- for (const member of members) {
3902
- const memberDir = (0, import_path5.join)(repoRootPath, member);
3903
- let memberPyproject = null;
3904
- try {
3905
- memberPyproject = await (0, import_build_utils7.readConfigFile)(
3906
- (0, import_path5.join)(memberDir, "pyproject.toml")
3907
- );
3908
- } catch (err) {
3909
- (0, import_build_utils7.debug)("Failed to parse workspace member pyproject.toml", err);
3910
- continue;
3911
- }
3912
- const projectName = memberPyproject?.project?.name;
3913
- if (projectName) {
3914
- nameToDir.set(projectName, memberDir);
3915
- }
3916
- }
3917
- const requirementLines = [];
3918
- for (const name of workspaceDepsForApp) {
3919
- const dir = nameToDir.get(name);
3920
- if (!dir) {
3921
- (0, import_build_utils7.debug)(
3922
- `uv workspace dependency "${name}" declared but corresponding member directory not found`
3923
- );
3924
- continue;
3925
- }
3926
- requirementLines.push(dir);
3927
- }
3928
- if (!requirementLines.length) {
3929
- return;
3930
- }
3931
- const tmpDir = await import_fs5.default.promises.mkdtemp(
3932
- (0, import_path5.join)(import_os2.default.tmpdir(), "vercel-uv-workspace-")
3933
- );
3934
- const reqPath = (0, import_path5.join)(tmpDir, "requirements.workspace.txt");
3935
- await import_fs5.default.promises.writeFile(reqPath, requirementLines.join("\n"));
3936
- await installRequirementsFile({
3937
- pythonPath,
3938
- pipPath,
3939
- uvPath,
3940
- filePath: reqPath,
3941
- workPath,
3942
- targetDir: vendorBaseDir,
3943
- meta
3944
- });
3945
- }
3946
-
3947
4228
  // src/index.ts
3948
- var readFile = (0, import_util.promisify)(import_fs6.default.readFile);
3949
- var writeFile = (0, import_util.promisify)(import_fs6.default.writeFile);
4229
+ var readFile = (0, import_util.promisify)(import_fs5.default.readFile);
4230
+ var writeFile = (0, import_util.promisify)(import_fs5.default.writeFile);
3950
4231
  var version = 3;
3951
- function findDir({
3952
- file,
3953
- entryDirectory,
3954
- workPath,
3955
- fsFiles
3956
- }) {
3957
- if (fsFiles[(0, import_path6.join)(entryDirectory, file)]) {
3958
- return (0, import_path6.join)(workPath, entryDirectory);
3959
- }
3960
- if (fsFiles[file]) {
3961
- return workPath;
3962
- }
3963
- return null;
3964
- }
3965
4232
  async function downloadFilesInWorkPath({
3966
4233
  entrypoint,
3967
4234
  workPath,
3968
4235
  files,
3969
4236
  meta = {}
3970
4237
  }) {
3971
- (0, import_build_utils8.debug)("Downloading user files...");
3972
- let downloadedFiles = await (0, import_build_utils8.download)(files, workPath, meta);
4238
+ (0, import_build_utils7.debug)("Downloading user files...");
4239
+ let downloadedFiles = await (0, import_build_utils7.download)(files, workPath, meta);
3973
4240
  if (meta.isDev) {
3974
- const { devCacheDir = (0, import_path6.join)(workPath, ".now", "cache") } = meta;
3975
- const destCache = (0, import_path6.join)(devCacheDir, (0, import_path6.basename)(entrypoint, ".py"));
3976
- await (0, import_build_utils8.download)(downloadedFiles, destCache);
3977
- downloadedFiles = await (0, import_build_utils8.glob)("**", destCache);
4241
+ const { devCacheDir = (0, import_path5.join)(workPath, ".now", "cache") } = meta;
4242
+ const destCache = (0, import_path5.join)(devCacheDir, (0, import_path5.basename)(entrypoint, ".py"));
4243
+ await (0, import_build_utils7.download)(downloadedFiles, destCache);
4244
+ downloadedFiles = await (0, import_build_utils7.glob)("**", destCache);
3978
4245
  workPath = destCache;
3979
4246
  }
3980
4247
  return workPath;
3981
4248
  }
3982
4249
  var build = async ({
3983
4250
  workPath,
3984
- repoRootPath,
3985
4251
  files: originalFiles,
3986
4252
  entrypoint,
3987
4253
  meta = {},
@@ -3996,7 +4262,7 @@ var build = async ({
3996
4262
  });
3997
4263
  try {
3998
4264
  if (meta.isDev) {
3999
- const setupCfg = (0, import_path6.join)(workPath, "setup.cfg");
4265
+ const setupCfg = (0, import_path5.join)(workPath, "setup.cfg");
4000
4266
  await writeFile(setupCfg, "[install]\nprefix=\n");
4001
4267
  }
4002
4268
  } catch (err) {
@@ -4009,8 +4275,8 @@ var build = async ({
4009
4275
  lockfileVersion,
4010
4276
  packageJsonPackageManager,
4011
4277
  turboSupportsCorepackHome
4012
- } = await (0, import_build_utils8.scanParentDirs)(workPath, true);
4013
- const spawnEnv = (0, import_build_utils8.getEnvForPackageManager)({
4278
+ } = await (0, import_build_utils7.scanParentDirs)(workPath, true);
4279
+ const spawnEnv = (0, import_build_utils7.getEnvForPackageManager)({
4014
4280
  cliType,
4015
4281
  lockfileVersion,
4016
4282
  packageJsonPackageManager,
@@ -4022,7 +4288,7 @@ var build = async ({
4022
4288
  if (typeof installCommand === "string") {
4023
4289
  if (installCommand.trim()) {
4024
4290
  console.log(`Running "install" command: \`${installCommand}\`...`);
4025
- await (0, import_build_utils8.execCommand)(installCommand, {
4291
+ await (0, import_build_utils7.execCommand)(installCommand, {
4026
4292
  env: spawnEnv,
4027
4293
  cwd: workPath
4028
4294
  });
@@ -4034,7 +4300,7 @@ var build = async ({
4034
4300
  config?.buildCommand;
4035
4301
  if (projectBuildCommand) {
4036
4302
  console.log(`Running "${projectBuildCommand}"`);
4037
- await (0, import_build_utils8.execCommand)(projectBuildCommand, {
4303
+ await (0, import_build_utils7.execCommand)(projectBuildCommand, {
4038
4304
  env: spawnEnv,
4039
4305
  cwd: workPath
4040
4306
  });
@@ -4046,7 +4312,7 @@ var build = async ({
4046
4312
  );
4047
4313
  }
4048
4314
  }
4049
- let fsFiles = await (0, import_build_utils8.glob)("**", workPath);
4315
+ let fsFiles = await (0, import_build_utils7.glob)("**", workPath);
4050
4316
  if ((framework === "fastapi" || framework === "flask") && (!fsFiles[entrypoint] || !entrypoint.endsWith(".py"))) {
4051
4317
  const detected = await detectPythonEntrypoint(
4052
4318
  config.framework,
@@ -4054,13 +4320,13 @@ var build = async ({
4054
4320
  entrypoint
4055
4321
  );
4056
4322
  if (detected) {
4057
- (0, import_build_utils8.debug)(
4323
+ (0, import_build_utils7.debug)(
4058
4324
  `Resolved Python entrypoint to "${detected}" (configured "${entrypoint}" not found).`
4059
4325
  );
4060
4326
  entrypoint = detected;
4061
4327
  } else {
4062
4328
  const searchedList = framework === "fastapi" ? FASTAPI_CANDIDATE_ENTRYPOINTS.join(", ") : FLASK_CANDIDATE_ENTRYPOINTS.join(", ");
4063
- throw new import_build_utils8.NowBuildError({
4329
+ throw new import_build_utils7.NowBuildError({
4064
4330
  code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
4065
4331
  message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
4066
4332
  link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
@@ -4068,46 +4334,42 @@ var build = async ({
4068
4334
  });
4069
4335
  }
4070
4336
  }
4071
- const entryDirectory = (0, import_path6.dirname)(entrypoint);
4072
- const hasReqLocal = !!fsFiles[(0, import_path6.join)(entryDirectory, "requirements.txt")];
4073
- const hasReqGlobal = !!fsFiles["requirements.txt"];
4074
- const uvLockDir = findDir({
4075
- file: "uv.lock",
4337
+ const entryDirectory = (0, import_path5.dirname)(entrypoint);
4338
+ const pyprojectDir = findDir({
4339
+ file: "pyproject.toml",
4076
4340
  entryDirectory,
4077
4341
  workPath,
4078
4342
  fsFiles
4079
4343
  });
4080
- const pyprojectDir = findDir({
4081
- file: "pyproject.toml",
4344
+ const pipfileLockDir = findDir({
4345
+ file: "Pipfile.lock",
4082
4346
  entryDirectory,
4083
4347
  workPath,
4084
4348
  fsFiles
4085
4349
  });
4086
- const pipfileLockDir = fsFiles[(0, import_path6.join)(entryDirectory, "Pipfile.lock")] ? (0, import_path6.join)(workPath, entryDirectory) : fsFiles["Pipfile.lock"] ? workPath : null;
4087
- const pipfileDir = fsFiles[(0, import_path6.join)(entryDirectory, "Pipfile")] ? (0, import_path6.join)(workPath, entryDirectory) : fsFiles["Pipfile"] ? workPath : null;
4088
4350
  let declaredPythonVersion;
4089
4351
  if (pyprojectDir) {
4090
4352
  let requiresPython;
4091
4353
  try {
4092
- const pyproject = await (0, import_build_utils9.readConfigFile)((0, import_path6.join)(pyprojectDir, "pyproject.toml"));
4354
+ const pyproject = await (0, import_build_utils8.readConfigFile)((0, import_path5.join)(pyprojectDir, "pyproject.toml"));
4093
4355
  requiresPython = pyproject?.project?.["requires-python"];
4094
4356
  } catch (err) {
4095
- (0, import_build_utils8.debug)("Failed to parse pyproject.toml", err);
4357
+ (0, import_build_utils7.debug)("Failed to parse pyproject.toml", err);
4096
4358
  }
4097
4359
  if (typeof requiresPython === "string" && requiresPython.trim()) {
4098
4360
  declaredPythonVersion = {
4099
4361
  version: requiresPython.trim(),
4100
4362
  source: "pyproject.toml"
4101
4363
  };
4102
- (0, import_build_utils8.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
4364
+ (0, import_build_utils7.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
4103
4365
  }
4104
4366
  } else if (pipfileLockDir) {
4105
4367
  let lock = {};
4106
4368
  try {
4107
- const json = await readFile((0, import_path6.join)(pipfileLockDir, "Pipfile.lock"), "utf8");
4369
+ const json = await readFile((0, import_path5.join)(pipfileLockDir, "Pipfile.lock"), "utf8");
4108
4370
  lock = JSON.parse(json);
4109
4371
  } catch (err) {
4110
- throw new import_build_utils8.NowBuildError({
4372
+ throw new import_build_utils7.NowBuildError({
4111
4373
  code: "INVALID_PIPFILE_LOCK",
4112
4374
  message: "Unable to parse Pipfile.lock"
4113
4375
  });
@@ -4115,191 +4377,55 @@ var build = async ({
4115
4377
  const pyFromLock = lock?._meta?.requires?.python_version;
4116
4378
  if (pyFromLock) {
4117
4379
  declaredPythonVersion = { version: pyFromLock, source: "Pipfile.lock" };
4118
- (0, import_build_utils8.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
4380
+ (0, import_build_utils7.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
4119
4381
  }
4120
4382
  }
4121
4383
  const pythonVersion = getSupportedPythonVersion({
4122
4384
  isDev: meta.isDev,
4123
4385
  declaredPythonVersion
4124
4386
  });
4125
- fsFiles = await (0, import_build_utils8.glob)("**", workPath);
4126
- const requirementsTxt = (0, import_path6.join)(entryDirectory, "requirements.txt");
4127
- const vendorBaseDir = (0, import_path6.join)(
4128
- workPath,
4129
- ".vercel",
4130
- "python",
4131
- `py${pythonVersion.version}`,
4132
- entryDirectory
4133
- );
4134
- try {
4135
- await import_fs6.default.promises.mkdir(vendorBaseDir, { recursive: true });
4136
- } catch (err) {
4137
- console.log("Failed to create vendor cache directory");
4138
- throw err;
4139
- }
4140
- let installationSource;
4141
- if (uvLockDir && pyprojectDir) {
4142
- installationSource = "uv.lock";
4143
- } else if (pyprojectDir) {
4144
- installationSource = "pyproject.toml";
4145
- } else if (pipfileLockDir) {
4146
- installationSource = "Pipfile.lock";
4147
- } else if (pipfileDir) {
4148
- installationSource = "Pipfile";
4149
- } else if (fsFiles[requirementsTxt] || fsFiles["requirements.txt"]) {
4150
- installationSource = "requirements.txt";
4151
- }
4152
- if (installationSource) {
4153
- console.log(
4154
- `Installing required dependencies from ${installationSource}...`
4155
- );
4156
- } else {
4157
- console.log("Installing required dependencies...");
4158
- }
4159
- let uvPath = null;
4387
+ fsFiles = await (0, import_build_utils7.glob)("**", workPath);
4388
+ const venvPath = (0, import_path5.join)(workPath, ".vercel", "python", ".venv");
4389
+ await ensureVenv({
4390
+ pythonPath: pythonVersion.pythonPath,
4391
+ venvPath
4392
+ });
4393
+ let uvPath;
4160
4394
  try {
4161
4395
  uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
4162
4396
  console.log(`Using uv at "${uvPath}"`);
4163
4397
  } catch (err) {
4164
- if (uvLockDir || pyprojectDir && !hasReqLocal && !hasReqGlobal) {
4165
- console.log("Failed to install uv");
4166
- throw new Error(
4167
- `uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
4168
- );
4169
- }
4170
- (0, import_build_utils8.debug)("Failed to install uv", err);
4398
+ console.log("Failed to install or locate uv");
4399
+ throw new Error(
4400
+ `uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
4401
+ );
4171
4402
  }
4172
- await installRequirement({
4403
+ const runtimeDependencies = framework === "flask" ? ["werkzeug>=1.0.1"] : ["werkzeug>=1.0.1", "uvicorn>=0.24"];
4404
+ const { projectDir } = await ensureUvProject({
4405
+ workPath,
4406
+ entryDirectory,
4407
+ fsFiles,
4173
4408
  pythonPath: pythonVersion.pythonPath,
4174
4409
  pipPath: pythonVersion.pipPath,
4175
4410
  uvPath,
4176
- dependency: "werkzeug",
4177
- version: "1.0.1",
4178
- workPath,
4179
- targetDir: vendorBaseDir,
4180
- meta
4411
+ venvPath,
4412
+ meta,
4413
+ runtimeDependencies
4181
4414
  });
4182
- if (framework !== "flask") {
4183
- await installRequirement({
4184
- pythonPath: pythonVersion.pythonPath,
4185
- pipPath: pythonVersion.pipPath,
4186
- uvPath,
4187
- dependency: "uvicorn",
4188
- version: "0.38.0",
4189
- workPath,
4190
- targetDir: vendorBaseDir,
4191
- meta
4192
- });
4193
- }
4194
- let installedFromProjectFiles = false;
4195
- if (uvLockDir) {
4196
- (0, import_build_utils8.debug)('Found "uv.lock"');
4197
- if (pyprojectDir) {
4198
- const exportedReq = await exportRequirementsFromUv(pyprojectDir, uvPath, {
4199
- locked: true
4200
- });
4201
- await installRequirementsFile({
4202
- pythonPath: pythonVersion.pythonPath,
4203
- pipPath: pythonVersion.pipPath,
4204
- uvPath,
4205
- filePath: exportedReq,
4206
- workPath,
4207
- targetDir: vendorBaseDir,
4208
- meta
4209
- });
4210
- installedFromProjectFiles = true;
4211
- } else {
4212
- (0, import_build_utils8.debug)('Skipping uv export because "pyproject.toml" was not found');
4213
- }
4214
- } else if (pyprojectDir) {
4215
- (0, import_build_utils8.debug)('Found "pyproject.toml"');
4216
- if (hasReqLocal || hasReqGlobal) {
4217
- console.log(
4218
- "Detected both pyproject.toml and requirements.txt but no lockfile; using pyproject.toml"
4219
- );
4220
- }
4221
- const exportedReq = await exportRequirementsFromUv(pyprojectDir, uvPath, {
4222
- locked: false
4223
- });
4224
- await installRequirementsFile({
4225
- pythonPath: pythonVersion.pythonPath,
4226
- pipPath: pythonVersion.pipPath,
4227
- uvPath,
4228
- filePath: exportedReq,
4229
- workPath,
4230
- targetDir: vendorBaseDir,
4231
- meta
4232
- });
4233
- installedFromProjectFiles = true;
4234
- } else if (pipfileLockDir || pipfileDir) {
4235
- (0, import_build_utils8.debug)(`Found ${pipfileLockDir ? '"Pipfile.lock"' : '"Pipfile"'}`);
4236
- if (hasReqLocal || hasReqGlobal) {
4237
- (0, import_build_utils8.debug)('Skipping Pipfile export because "requirements.txt" exists');
4238
- } else {
4239
- const exportedReq = await exportRequirementsFromPipfile({
4240
- pythonPath: pythonVersion.pythonPath,
4241
- pipPath: pythonVersion.pipPath,
4242
- uvPath,
4243
- projectDir: pipfileLockDir || pipfileDir,
4244
- meta
4245
- });
4246
- await installRequirementsFile({
4247
- pythonPath: pythonVersion.pythonPath,
4248
- pipPath: pythonVersion.pipPath,
4249
- uvPath,
4250
- filePath: exportedReq,
4251
- workPath,
4252
- targetDir: vendorBaseDir,
4253
- meta
4254
- });
4255
- installedFromProjectFiles = true;
4256
- }
4257
- }
4258
- if (!installedFromProjectFiles && fsFiles[requirementsTxt]) {
4259
- (0, import_build_utils8.debug)('Found local "requirements.txt"');
4260
- const requirementsTxtPath = fsFiles[requirementsTxt].fsPath;
4261
- await installRequirementsFile({
4262
- pythonPath: pythonVersion.pythonPath,
4263
- pipPath: pythonVersion.pipPath,
4264
- uvPath,
4265
- filePath: requirementsTxtPath,
4266
- workPath,
4267
- targetDir: vendorBaseDir,
4268
- meta
4269
- });
4270
- } else if (!installedFromProjectFiles && fsFiles["requirements.txt"]) {
4271
- (0, import_build_utils8.debug)('Found global "requirements.txt"');
4272
- const requirementsTxtPath = fsFiles["requirements.txt"].fsPath;
4273
- await installRequirementsFile({
4274
- pythonPath: pythonVersion.pythonPath,
4275
- pipPath: pythonVersion.pipPath,
4276
- uvPath,
4277
- filePath: requirementsTxtPath,
4278
- workPath,
4279
- targetDir: vendorBaseDir,
4280
- meta
4281
- });
4282
- }
4283
- if (pyprojectDir && repoRootPath) {
4284
- await installUvWorkspaceDependencies({
4285
- repoRootPath,
4286
- pyprojectDir,
4287
- pythonPath: pythonVersion.pythonPath,
4288
- pipPath: pythonVersion.pipPath,
4289
- uvPath,
4290
- workPath,
4291
- vendorBaseDir,
4292
- meta
4293
- });
4294
- }
4295
- const originalPyPath = (0, import_path6.join)(__dirname, "..", "vc_init.py");
4415
+ await runUvSync({
4416
+ uvPath,
4417
+ venvPath,
4418
+ projectDir,
4419
+ locked: true
4420
+ });
4421
+ const originalPyPath = (0, import_path5.join)(__dirname, "..", "vc_init.py");
4296
4422
  const originalHandlerPyContents = await readFile(originalPyPath, "utf8");
4297
- (0, import_build_utils8.debug)("Entrypoint is", entrypoint);
4423
+ (0, import_build_utils7.debug)("Entrypoint is", entrypoint);
4298
4424
  const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
4299
4425
  const vendorDir = resolveVendorDir();
4300
4426
  const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
4301
4427
  const entrypointWithSuffix = `${entrypoint}${suffix}`;
4302
- (0, import_build_utils8.debug)("Entrypoint with suffix is", entrypointWithSuffix);
4428
+ (0, import_build_utils7.debug)("Entrypoint with suffix is", entrypointWithSuffix);
4303
4429
  const handlerPyContents = originalHandlerPyContents.replace(/__VC_HANDLER_MODULE_NAME/g, moduleName).replace(/__VC_HANDLER_ENTRYPOINT/g, entrypointWithSuffix).replace(/__VC_HANDLER_VENDOR_DIR/g, vendorDir);
4304
4430
  const predefinedExcludes = [
4305
4431
  ".git/**",
@@ -4325,26 +4451,21 @@ var build = async ({
4325
4451
  cwd: workPath,
4326
4452
  ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
4327
4453
  };
4328
- const files = await (0, import_build_utils8.glob)("**", globOptions);
4329
- try {
4330
- const cachedVendorAbs = (0, import_path6.join)(vendorBaseDir, resolveVendorDir());
4331
- if (import_fs6.default.existsSync(cachedVendorAbs)) {
4332
- const vendorFiles = await (0, import_build_utils8.glob)("**", cachedVendorAbs, resolveVendorDir());
4333
- for (const [p, f] of Object.entries(vendorFiles)) {
4334
- files[p] = f;
4335
- }
4336
- }
4337
- } catch (err) {
4338
- console.log("Failed to include cached vendor directory");
4339
- throw err;
4454
+ const files = await (0, import_build_utils7.glob)("**", globOptions);
4455
+ const vendorFiles = await mirrorSitePackagesIntoVendor({
4456
+ venvPath,
4457
+ vendorDirName: vendorDir
4458
+ });
4459
+ for (const [p, f] of Object.entries(vendorFiles)) {
4460
+ files[p] = f;
4340
4461
  }
4341
4462
  const handlerPyFilename = "vc__handler__python";
4342
- files[`${handlerPyFilename}.py`] = new import_build_utils8.FileBlob({ data: handlerPyContents });
4463
+ files[`${handlerPyFilename}.py`] = new import_build_utils7.FileBlob({ data: handlerPyContents });
4343
4464
  if (config.framework === "fasthtml") {
4344
4465
  const { SESSKEY = "" } = process.env;
4345
- files[".sesskey"] = new import_build_utils8.FileBlob({ data: `"${SESSKEY}"` });
4466
+ files[".sesskey"] = new import_build_utils7.FileBlob({ data: `"${SESSKEY}"` });
4346
4467
  }
4347
- const output = new import_build_utils8.Lambda({
4468
+ const output = new import_build_utils7.Lambda({
4348
4469
  files,
4349
4470
  handler: `${handlerPyFilename}.vc_handler`,
4350
4471
  runtime: pythonVersion.runtime,
@@ -4380,7 +4501,7 @@ var defaultShouldServe = ({
4380
4501
  if (entrypoint === requestPath && hasProp(files, entrypoint)) {
4381
4502
  return true;
4382
4503
  }
4383
- const { dir, name } = (0, import_path6.parse)(entrypoint);
4504
+ const { dir, name } = (0, import_path5.parse)(entrypoint);
4384
4505
  if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
4385
4506
  return true;
4386
4507
  }