@vercel/python 5.0.5 → 5.0.7

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
@@ -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 fs3 = 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
- fs3.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(fs3.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 fs3 = require("fs");
91
+ var fs5 = require("fs");
92
92
  function isexe(path, options, cb) {
93
- fs3.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(fs3.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 fs3 = 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 fs3 = 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 = fs3.openSync(command, "r");
412
- fs3.readSync(fd, buffer, 0, size, 0);
413
- fs3.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());
@@ -423,15 +423,15 @@ var require_readShebang = __commonJS({
423
423
  var require_semver = __commonJS({
424
424
  "../../node_modules/.pnpm/semver@5.7.2/node_modules/semver/semver.js"(exports, module2) {
425
425
  exports = module2.exports = SemVer;
426
- var debug3;
426
+ var debug5;
427
427
  if (typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG)) {
428
- debug3 = function() {
428
+ debug5 = function() {
429
429
  var args = Array.prototype.slice.call(arguments, 0);
430
430
  args.unshift("SEMVER");
431
431
  console.log.apply(console, args);
432
432
  };
433
433
  } else {
434
- debug3 = function() {
434
+ debug5 = function() {
435
435
  };
436
436
  }
437
437
  exports.SEMVER_SPEC_VERSION = "2.0.0";
@@ -540,15 +540,15 @@ var require_semver = __commonJS({
540
540
  var STAR = R++;
541
541
  src[STAR] = "(<|>)?=?\\s*\\*";
542
542
  for (i = 0; i < R; i++) {
543
- debug3(i, src[i]);
543
+ debug5(i, src[i]);
544
544
  if (!re[i]) {
545
545
  re[i] = new RegExp(src[i]);
546
546
  safeRe[i] = new RegExp(makeSafeRe(src[i]));
547
547
  }
548
548
  }
549
549
  var i;
550
- exports.parse = parse;
551
- function parse(version2, options) {
550
+ exports.parse = parse2;
551
+ function parse2(version2, options) {
552
552
  if (!options || typeof options !== "object") {
553
553
  options = {
554
554
  loose: !!options,
@@ -576,12 +576,12 @@ var require_semver = __commonJS({
576
576
  }
577
577
  exports.valid = valid;
578
578
  function valid(version2, options) {
579
- var v = parse(version2, options);
579
+ var v = parse2(version2, options);
580
580
  return v ? v.version : null;
581
581
  }
582
582
  exports.clean = clean;
583
583
  function clean(version2, options) {
584
- var s = parse(version2.trim().replace(/^[=v]+/, ""), options);
584
+ var s = parse2(version2.trim().replace(/^[=v]+/, ""), options);
585
585
  return s ? s.version : null;
586
586
  }
587
587
  exports.SemVer = SemVer;
@@ -607,7 +607,7 @@ var require_semver = __commonJS({
607
607
  if (!(this instanceof SemVer)) {
608
608
  return new SemVer(version2, options);
609
609
  }
610
- debug3("SemVer", version2, options);
610
+ debug5("SemVer", version2, options);
611
611
  this.options = options;
612
612
  this.loose = !!options.loose;
613
613
  var m = version2.trim().match(options.loose ? safeRe[LOOSE] : safeRe[FULL]);
@@ -654,7 +654,7 @@ var require_semver = __commonJS({
654
654
  return this.version;
655
655
  };
656
656
  SemVer.prototype.compare = function(other) {
657
- debug3("SemVer.compare", this.version, this.options, other);
657
+ debug5("SemVer.compare", this.version, this.options, other);
658
658
  if (!(other instanceof SemVer)) {
659
659
  other = new SemVer(other, this.options);
660
660
  }
@@ -681,7 +681,7 @@ var require_semver = __commonJS({
681
681
  do {
682
682
  var a = this.prerelease[i2];
683
683
  var b = other.prerelease[i2];
684
- debug3("prerelease compare", i2, a, b);
684
+ debug5("prerelease compare", i2, a, b);
685
685
  if (a === void 0 && b === void 0) {
686
686
  return 0;
687
687
  } else if (b === void 0) {
@@ -791,8 +791,8 @@ var require_semver = __commonJS({
791
791
  if (eq(version1, version2)) {
792
792
  return null;
793
793
  } else {
794
- var v1 = parse(version1);
795
- var v2 = parse(version2);
794
+ var v1 = parse2(version1);
795
+ var v2 = parse2(version2);
796
796
  var prefix = "";
797
797
  if (v1.prerelease.length || v2.prerelease.length) {
798
798
  prefix = "pre";
@@ -935,7 +935,7 @@ var require_semver = __commonJS({
935
935
  return new Comparator(comp, options);
936
936
  }
937
937
  comp = comp.trim().split(/\s+/).join(" ");
938
- debug3("comparator", comp, options);
938
+ debug5("comparator", comp, options);
939
939
  this.options = options;
940
940
  this.loose = !!options.loose;
941
941
  this.parse(comp);
@@ -944,7 +944,7 @@ var require_semver = __commonJS({
944
944
  } else {
945
945
  this.value = this.operator + this.semver.version;
946
946
  }
947
- debug3("comp", this);
947
+ debug5("comp", this);
948
948
  }
949
949
  var ANY = {};
950
950
  Comparator.prototype.parse = function(comp) {
@@ -967,7 +967,7 @@ var require_semver = __commonJS({
967
967
  return this.value;
968
968
  };
969
969
  Comparator.prototype.test = function(version2) {
970
- debug3("Comparator.test", version2, this.options.loose);
970
+ debug5("Comparator.test", version2, this.options.loose);
971
971
  if (this.semver === ANY) {
972
972
  return true;
973
973
  }
@@ -1050,9 +1050,9 @@ var require_semver = __commonJS({
1050
1050
  var loose = this.options.loose;
1051
1051
  var hr = loose ? safeRe[HYPHENRANGELOOSE] : safeRe[HYPHENRANGE];
1052
1052
  range = range.replace(hr, hyphenReplace);
1053
- debug3("hyphen replace", range);
1053
+ debug5("hyphen replace", range);
1054
1054
  range = range.replace(safeRe[COMPARATORTRIM], comparatorTrimReplace);
1055
- debug3("comparator trim", range, safeRe[COMPARATORTRIM]);
1055
+ debug5("comparator trim", range, safeRe[COMPARATORTRIM]);
1056
1056
  range = range.replace(safeRe[TILDETRIM], tildeTrimReplace);
1057
1057
  range = range.replace(safeRe[CARETTRIM], caretTrimReplace);
1058
1058
  var compRe = loose ? safeRe[COMPARATORLOOSE] : safeRe[COMPARATOR];
@@ -1092,15 +1092,15 @@ var require_semver = __commonJS({
1092
1092
  });
1093
1093
  }
1094
1094
  function parseComparator(comp, options) {
1095
- debug3("comp", comp, options);
1095
+ debug5("comp", comp, options);
1096
1096
  comp = replaceCarets(comp, options);
1097
- debug3("caret", comp);
1097
+ debug5("caret", comp);
1098
1098
  comp = replaceTildes(comp, options);
1099
- debug3("tildes", comp);
1099
+ debug5("tildes", comp);
1100
1100
  comp = replaceXRanges(comp, options);
1101
- debug3("xrange", comp);
1101
+ debug5("xrange", comp);
1102
1102
  comp = replaceStars(comp, options);
1103
- debug3("stars", comp);
1103
+ debug5("stars", comp);
1104
1104
  return comp;
1105
1105
  }
1106
1106
  function isX(id) {
@@ -1114,7 +1114,7 @@ var require_semver = __commonJS({
1114
1114
  function replaceTilde(comp, options) {
1115
1115
  var r = options.loose ? safeRe[TILDELOOSE] : safeRe[TILDE];
1116
1116
  return comp.replace(r, function(_, M, m, p, pr) {
1117
- debug3("tilde", comp, _, M, m, p, pr);
1117
+ debug5("tilde", comp, _, M, m, p, pr);
1118
1118
  var ret;
1119
1119
  if (isX(M)) {
1120
1120
  ret = "";
@@ -1123,12 +1123,12 @@ var require_semver = __commonJS({
1123
1123
  } else if (isX(p)) {
1124
1124
  ret = ">=" + M + "." + m + ".0 <" + M + "." + (+m + 1) + ".0";
1125
1125
  } else if (pr) {
1126
- debug3("replaceTilde pr", pr);
1126
+ debug5("replaceTilde pr", pr);
1127
1127
  ret = ">=" + M + "." + m + "." + p + "-" + pr + " <" + M + "." + (+m + 1) + ".0";
1128
1128
  } else {
1129
1129
  ret = ">=" + M + "." + m + "." + p + " <" + M + "." + (+m + 1) + ".0";
1130
1130
  }
1131
- debug3("tilde return", ret);
1131
+ debug5("tilde return", ret);
1132
1132
  return ret;
1133
1133
  });
1134
1134
  }
@@ -1138,10 +1138,10 @@ var require_semver = __commonJS({
1138
1138
  }).join(" ");
1139
1139
  }
1140
1140
  function replaceCaret(comp, options) {
1141
- debug3("caret", comp, options);
1141
+ debug5("caret", comp, options);
1142
1142
  var r = options.loose ? safeRe[CARETLOOSE] : safeRe[CARET];
1143
1143
  return comp.replace(r, function(_, M, m, p, pr) {
1144
- debug3("caret", comp, _, M, m, p, pr);
1144
+ debug5("caret", comp, _, M, m, p, pr);
1145
1145
  var ret;
1146
1146
  if (isX(M)) {
1147
1147
  ret = "";
@@ -1154,7 +1154,7 @@ var require_semver = __commonJS({
1154
1154
  ret = ">=" + M + "." + m + ".0 <" + (+M + 1) + ".0.0";
1155
1155
  }
1156
1156
  } else if (pr) {
1157
- debug3("replaceCaret pr", pr);
1157
+ debug5("replaceCaret pr", pr);
1158
1158
  if (M === "0") {
1159
1159
  if (m === "0") {
1160
1160
  ret = ">=" + M + "." + m + "." + p + "-" + pr + " <" + M + "." + m + "." + (+p + 1);
@@ -1165,7 +1165,7 @@ var require_semver = __commonJS({
1165
1165
  ret = ">=" + M + "." + m + "." + p + "-" + pr + " <" + (+M + 1) + ".0.0";
1166
1166
  }
1167
1167
  } else {
1168
- debug3("no pr");
1168
+ debug5("no pr");
1169
1169
  if (M === "0") {
1170
1170
  if (m === "0") {
1171
1171
  ret = ">=" + M + "." + m + "." + p + " <" + M + "." + m + "." + (+p + 1);
@@ -1176,12 +1176,12 @@ var require_semver = __commonJS({
1176
1176
  ret = ">=" + M + "." + m + "." + p + " <" + (+M + 1) + ".0.0";
1177
1177
  }
1178
1178
  }
1179
- debug3("caret return", ret);
1179
+ debug5("caret return", ret);
1180
1180
  return ret;
1181
1181
  });
1182
1182
  }
1183
1183
  function replaceXRanges(comp, options) {
1184
- debug3("replaceXRanges", comp, options);
1184
+ debug5("replaceXRanges", comp, options);
1185
1185
  return comp.split(/\s+/).map(function(comp2) {
1186
1186
  return replaceXRange(comp2, options);
1187
1187
  }).join(" ");
@@ -1190,7 +1190,7 @@ var require_semver = __commonJS({
1190
1190
  comp = comp.trim();
1191
1191
  var r = options.loose ? safeRe[XRANGELOOSE] : safeRe[XRANGE];
1192
1192
  return comp.replace(r, function(ret, gtlt, M, m, p, pr) {
1193
- debug3("xRange", comp, ret, gtlt, M, m, p, pr);
1193
+ debug5("xRange", comp, ret, gtlt, M, m, p, pr);
1194
1194
  var xM = isX(M);
1195
1195
  var xm = xM || isX(m);
1196
1196
  var xp = xm || isX(p);
@@ -1233,12 +1233,12 @@ var require_semver = __commonJS({
1233
1233
  } else if (xp) {
1234
1234
  ret = ">=" + M + "." + m + ".0 <" + M + "." + (+m + 1) + ".0";
1235
1235
  }
1236
- debug3("xRange return", ret);
1236
+ debug5("xRange return", ret);
1237
1237
  return ret;
1238
1238
  });
1239
1239
  }
1240
1240
  function replaceStars(comp, options) {
1241
- debug3("replaceStars", comp, options);
1241
+ debug5("replaceStars", comp, options);
1242
1242
  return comp.trim().replace(safeRe[STAR], "");
1243
1243
  }
1244
1244
  function hyphenReplace($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr, tb) {
@@ -1286,7 +1286,7 @@ var require_semver = __commonJS({
1286
1286
  }
1287
1287
  if (version2.prerelease.length && !options.includePrerelease) {
1288
1288
  for (i2 = 0; i2 < set.length; i2++) {
1289
- debug3(set[i2].semver);
1289
+ debug5(set[i2].semver);
1290
1290
  if (set[i2].semver === ANY) {
1291
1291
  continue;
1292
1292
  }
@@ -1462,7 +1462,7 @@ var require_semver = __commonJS({
1462
1462
  }
1463
1463
  exports.prerelease = prerelease;
1464
1464
  function prerelease(version2, options) {
1465
- var parsed = parse(version2, options);
1465
+ var parsed = parse2(version2, options);
1466
1466
  return parsed && parsed.prerelease.length ? parsed.prerelease : null;
1467
1467
  }
1468
1468
  exports.intersects = intersects;
@@ -1483,7 +1483,7 @@ var require_semver = __commonJS({
1483
1483
  if (match == null) {
1484
1484
  return null;
1485
1485
  }
1486
- return parse(match[1] + "." + (match[2] || "0") + "." + (match[3] || "0"));
1486
+ return parse2(match[1] + "." + (match[2] || "0") + "." + (match[3] || "0"));
1487
1487
  }
1488
1488
  }
1489
1489
  });
@@ -1551,7 +1551,7 @@ var require_parse = __commonJS({
1551
1551
  }
1552
1552
  return parsed;
1553
1553
  }
1554
- function parse(command, args, options) {
1554
+ function parse2(command, args, options) {
1555
1555
  if (args && !Array.isArray(args)) {
1556
1556
  options = args;
1557
1557
  args = null;
@@ -1570,7 +1570,7 @@ var require_parse = __commonJS({
1570
1570
  };
1571
1571
  return options.shell ? parseShell(parsed) : parseNonShell(parsed);
1572
1572
  }
1573
- module2.exports = parse;
1573
+ module2.exports = parse2;
1574
1574
  }
1575
1575
  });
1576
1576
 
@@ -1629,24 +1629,24 @@ var require_cross_spawn = __commonJS({
1629
1629
  "../../node_modules/.pnpm/cross-spawn@6.0.5/node_modules/cross-spawn/index.js"(exports, module2) {
1630
1630
  "use strict";
1631
1631
  var cp = require("child_process");
1632
- var parse = require_parse();
1632
+ var parse2 = require_parse();
1633
1633
  var enoent = require_enoent();
1634
- function spawn(command, args, options) {
1635
- const parsed = parse(command, args, options);
1634
+ function spawn3(command, args, options) {
1635
+ const parsed = parse2(command, args, options);
1636
1636
  const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
1637
1637
  enoent.hookChildProcess(spawned, parsed);
1638
1638
  return spawned;
1639
1639
  }
1640
1640
  function spawnSync(command, args, options) {
1641
- const parsed = parse(command, args, options);
1641
+ const parsed = parse2(command, args, options);
1642
1642
  const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
1643
1643
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
1644
1644
  return result;
1645
1645
  }
1646
- module2.exports = spawn;
1647
- module2.exports.spawn = spawn;
1646
+ module2.exports = spawn3;
1647
+ module2.exports.spawn = spawn3;
1648
1648
  module2.exports.sync = spawnSync;
1649
- module2.exports._parse = parse;
1649
+ module2.exports._parse = parse2;
1650
1650
  module2.exports._enoent = enoent;
1651
1651
  }
1652
1652
  });
@@ -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 fs3;
1898
+ var fs5;
1899
1899
  try {
1900
- fs3 = 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 (!fs3)
1912
+ if (!fs5)
1913
1913
  return false;
1914
- return (stream instanceof (fs3.ReadStream || noop) || stream instanceof (fs3.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);
@@ -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: join3, delimiter, sep, posix } = require("path");
2654
+ var { join: join5, 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 + join3(pathPart, cmd);
2683
+ return prefix + join5(pathPart, cmd);
2684
2684
  };
2685
2685
  var which3 = async (cmd, opt = {}) => {
2686
2686
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -2739,18 +2739,19 @@ var require_lib = __commonJS({
2739
2739
  var src_exports = {};
2740
2740
  __export(src_exports, {
2741
2741
  build: () => build,
2742
+ defaultShouldServe: () => defaultShouldServe,
2742
2743
  downloadFilesInWorkPath: () => downloadFilesInWorkPath,
2743
2744
  installRequirement: () => installRequirement,
2744
2745
  installRequirementsFile: () => installRequirementsFile,
2745
- shouldServe: () => import_build_utils3.shouldServe,
2746
+ shouldServe: () => shouldServe,
2747
+ startDevServer: () => startDevServer,
2746
2748
  version: () => version
2747
2749
  });
2748
2750
  module.exports = __toCommonJS(src_exports);
2749
- var import_fs2 = __toESM(require("fs"));
2750
- var import_execa2 = __toESM(require_execa());
2751
+ var import_fs5 = __toESM(require("fs"));
2751
2752
  var import_util = require("util");
2752
- var import_path2 = require("path");
2753
- var import_build_utils3 = require("@vercel/build-utils");
2753
+ var import_path5 = require("path");
2754
+ var import_build_utils5 = require("@vercel/build-utils");
2754
2755
 
2755
2756
  // src/install.ts
2756
2757
  var import_execa = __toESM(require_execa());
@@ -2835,16 +2836,10 @@ async function getUserScriptsDir(pythonPath) {
2835
2836
  return null;
2836
2837
  }
2837
2838
  }
2838
- async function pipInstall(pipPath, pythonPath, workPath, args) {
2839
- const target = resolveVendorDir();
2839
+ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
2840
+ const target = targetDir ? (0, import_path.join)(targetDir, resolveVendorDir()) : resolveVendorDir();
2840
2841
  process.env.PIP_USER = "0";
2841
- let uvBin = null;
2842
- try {
2843
- uvBin = await getUvBinaryOrInstall(pythonPath);
2844
- } catch (err) {
2845
- console.log("Failed to install uv, falling back to pip");
2846
- }
2847
- if (uvBin) {
2842
+ if (uvPath) {
2848
2843
  const uvArgs = [
2849
2844
  "pip",
2850
2845
  "install",
@@ -2854,15 +2849,16 @@ async function pipInstall(pipPath, pythonPath, workPath, args) {
2854
2849
  target,
2855
2850
  ...args
2856
2851
  ];
2857
- const prettyUv = `${uvBin} ${uvArgs.join(" ")}`;
2852
+ const prettyUv = `${uvPath} ${uvArgs.join(" ")}`;
2858
2853
  (0, import_build_utils.debug)(`Running "${prettyUv}"...`);
2859
2854
  try {
2860
- await (0, import_execa.default)(uvBin, uvArgs, {
2855
+ await (0, import_execa.default)(uvPath, uvArgs, {
2861
2856
  cwd: workPath
2862
2857
  });
2863
2858
  return;
2864
2859
  } catch (err) {
2865
2860
  console.log(`Failed to run "${prettyUv}", falling back to pip`);
2861
+ (0, import_build_utils.debug)(`error: ${err}`);
2866
2862
  }
2867
2863
  }
2868
2864
  const cmdArgs = [
@@ -2882,11 +2878,12 @@ async function pipInstall(pipPath, pythonPath, workPath, args) {
2882
2878
  });
2883
2879
  } catch (err) {
2884
2880
  console.log(`Failed to run "${pretty}"`);
2881
+ (0, import_build_utils.debug)(`error: ${err}`);
2885
2882
  throw err;
2886
2883
  }
2887
2884
  }
2888
2885
  async function maybeFindUvBin(pythonPath) {
2889
- const found = import_which.default.sync(uvExec, { nothrow: true });
2886
+ const found = import_which.default.sync("uv", { nothrow: true });
2890
2887
  if (found)
2891
2888
  return found;
2892
2889
  try {
@@ -2897,10 +2894,7 @@ async function maybeFindUvBin(pythonPath) {
2897
2894
  return uvPath;
2898
2895
  }
2899
2896
  } catch (err) {
2900
- (0, import_build_utils.debug)(
2901
- "Failed to resolve uv from interpreter's global scripts directory",
2902
- err
2903
- );
2897
+ (0, import_build_utils.debug)("Failed to resolve Python global scripts directory", err);
2904
2898
  }
2905
2899
  try {
2906
2900
  const userScriptsDir = await getUserScriptsDir(pythonPath);
@@ -2910,10 +2904,7 @@ async function maybeFindUvBin(pythonPath) {
2910
2904
  return uvPath;
2911
2905
  }
2912
2906
  } catch (err) {
2913
- (0, import_build_utils.debug)(
2914
- "Failed to resolve uv from interpreter's user scripts directory",
2915
- err
2916
- );
2907
+ (0, import_build_utils.debug)("Failed to resolve Python user scripts directory", err);
2917
2908
  }
2918
2909
  try {
2919
2910
  const candidates = [];
@@ -2935,10 +2926,8 @@ async function maybeFindUvBin(pythonPath) {
2935
2926
  }
2936
2927
  async function getUvBinaryOrInstall(pythonPath) {
2937
2928
  const uvBin = await maybeFindUvBin(pythonPath);
2938
- if (uvBin) {
2939
- console.log(`Using uv at "${uvBin}"`);
2929
+ if (uvBin)
2940
2930
  return uvBin;
2941
- }
2942
2931
  try {
2943
2932
  console.log("Installing uv...");
2944
2933
  await (0, import_execa.default)(
@@ -2969,41 +2958,116 @@ async function getUvBinaryOrInstall(pythonPath) {
2969
2958
  async function installRequirement({
2970
2959
  pythonPath,
2971
2960
  pipPath,
2961
+ uvPath,
2972
2962
  dependency,
2973
2963
  version: version2,
2974
2964
  workPath,
2965
+ targetDir,
2975
2966
  meta,
2976
2967
  args = []
2977
2968
  }) {
2978
- if (meta.isDev && await isInstalled(pythonPath, dependency, workPath)) {
2969
+ const actualTargetDir = targetDir || workPath;
2970
+ if (meta.isDev && await isInstalled(pythonPath, dependency, actualTargetDir)) {
2979
2971
  (0, import_build_utils.debug)(
2980
- `Skipping ${dependency} dependency installation, already installed in ${workPath}`
2972
+ `Skipping ${dependency} dependency installation, already installed in ${actualTargetDir}`
2981
2973
  );
2982
2974
  return;
2983
2975
  }
2984
2976
  const exact = `${dependency}==${version2}`;
2985
- await pipInstall(pipPath, pythonPath, workPath, [exact, ...args]);
2977
+ await pipInstall(pipPath, uvPath, workPath, [exact, ...args], targetDir);
2986
2978
  }
2987
2979
  async function installRequirementsFile({
2988
2980
  pythonPath,
2989
2981
  pipPath,
2982
+ uvPath,
2990
2983
  filePath,
2991
2984
  workPath,
2985
+ targetDir,
2992
2986
  meta,
2993
2987
  args = []
2994
2988
  }) {
2995
- if (meta.isDev && await areRequirementsInstalled(pythonPath, filePath, workPath)) {
2989
+ const actualTargetDir = targetDir || workPath;
2990
+ if (meta.isDev && await areRequirementsInstalled(pythonPath, filePath, actualTargetDir)) {
2996
2991
  (0, import_build_utils.debug)(`Skipping requirements file installation, already installed`);
2997
2992
  return;
2998
2993
  }
2999
- await pipInstall(pipPath, pythonPath, workPath, [
3000
- "--upgrade",
3001
- "-r",
3002
- filePath,
3003
- ...args
3004
- ]);
2994
+ await pipInstall(
2995
+ pipPath,
2996
+ uvPath,
2997
+ workPath,
2998
+ ["--upgrade", "-r", filePath, ...args],
2999
+ targetDir
3000
+ );
3001
+ }
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 = ["export"];
3008
+ if (locked) {
3009
+ args.push("--frozen");
3010
+ }
3011
+ (0, import_build_utils.debug)(`Running "${uvPath} ${args.join(" ")}" in ${projectDir}...`);
3012
+ let stdout;
3013
+ try {
3014
+ const { stdout: out } = await (0, import_execa.default)(uvPath, args, { cwd: projectDir });
3015
+ stdout = out;
3016
+ } catch (err) {
3017
+ throw new Error(
3018
+ `Failed to run "${uvPath} ${args.join(" ")}": ${err instanceof Error ? err.message : String(err)}`
3019
+ );
3020
+ }
3021
+ const tmpDir = await import_fs.default.promises.mkdtemp((0, import_path.join)(import_os.default.tmpdir(), "vercel-uv-"));
3022
+ const outPath = (0, import_path.join)(tmpDir, "requirements.uv.txt");
3023
+ await import_fs.default.promises.writeFile(outPath, stdout);
3024
+ (0, import_build_utils.debug)(`Exported requirements to ${outPath}`);
3025
+ return outPath;
3026
+ }
3027
+ async function exportRequirementsFromPipfile({
3028
+ pythonPath,
3029
+ pipPath,
3030
+ uvPath,
3031
+ projectDir,
3032
+ meta
3033
+ }) {
3034
+ const tempDir = await import_fs.default.promises.mkdtemp(
3035
+ (0, import_path.join)(import_os.default.tmpdir(), "vercel-pipenv-")
3036
+ );
3037
+ await installRequirement({
3038
+ pythonPath,
3039
+ pipPath,
3040
+ dependency: "pipfile-requirements",
3041
+ version: "0.3.0",
3042
+ workPath: tempDir,
3043
+ meta,
3044
+ args: ["--no-warn-script-location"],
3045
+ uvPath
3046
+ });
3047
+ const tempVendorDir = (0, import_path.join)(tempDir, resolveVendorDir());
3048
+ const convertCmd = isWin ? (0, import_path.join)(tempVendorDir, "Scripts", "pipfile2req.exe") : (0, import_path.join)(tempVendorDir, "bin", "pipfile2req");
3049
+ (0, import_build_utils.debug)(`Running "${convertCmd}" in ${projectDir}...`);
3050
+ let stdout;
3051
+ try {
3052
+ const { stdout: out } = await (0, import_execa.default)(convertCmd, [], {
3053
+ cwd: projectDir,
3054
+ env: { ...process.env, PYTHONPATH: tempVendorDir }
3055
+ });
3056
+ stdout = out;
3057
+ } catch (err) {
3058
+ throw new Error(
3059
+ `Failed to run "${convertCmd}": ${err instanceof Error ? err.message : String(err)}`
3060
+ );
3061
+ }
3062
+ const outPath = (0, import_path.join)(tempDir, "requirements.pipenv.txt");
3063
+ await import_fs.default.promises.writeFile(outPath, stdout);
3064
+ (0, import_build_utils.debug)(`Exported pipfile requirements to ${outPath}`);
3065
+ return outPath;
3005
3066
  }
3006
3067
 
3068
+ // src/index.ts
3069
+ var import_build_utils6 = require("@vercel/build-utils");
3070
+
3007
3071
  // src/version.ts
3008
3072
  var import_build_utils2 = require("@vercel/build-utils");
3009
3073
  var import_which2 = __toESM(require_lib());
@@ -3066,35 +3130,59 @@ function getLatestPythonVersion({
3066
3130
  }
3067
3131
  function getSupportedPythonVersion({
3068
3132
  isDev,
3069
- pipLockPythonVersion
3133
+ declaredPythonVersion
3070
3134
  }) {
3071
3135
  if (isDev) {
3072
3136
  return getDevPythonVersion();
3073
3137
  }
3074
3138
  let selection = getLatestPythonVersion({ isDev: false });
3075
- if (typeof pipLockPythonVersion === "string") {
3076
- const found = allOptions.find(
3077
- (o) => o.version === pipLockPythonVersion && isInstalled2(o)
3078
- );
3079
- if (found) {
3080
- selection = found;
3139
+ if (declaredPythonVersion) {
3140
+ const { version: version2, source } = declaredPythonVersion;
3141
+ const requested = allOptions.find((o) => o.version === version2);
3142
+ if (requested) {
3143
+ if (isDiscontinued(requested)) {
3144
+ throw new import_build_utils2.NowBuildError({
3145
+ code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
3146
+ link: "http://vercel.link/python-version",
3147
+ message: `Python version "${requested.version}" detected in ${source} is discontinued and must be upgraded.`
3148
+ });
3149
+ }
3150
+ if (isInstalled2(requested)) {
3151
+ selection = requested;
3152
+ console.log(`Using Python ${selection.version} from ${source}`);
3153
+ } else {
3154
+ console.warn(
3155
+ `Warning: Python version "${version2}" detected in ${source} is not installed and will be ignored. http://vercel.link/python-version`
3156
+ );
3157
+ console.log(
3158
+ `Falling back to latest installed version: ${selection.version}`
3159
+ );
3160
+ }
3081
3161
  } else {
3082
3162
  console.warn(
3083
- `Warning: Python version "${pipLockPythonVersion}" detected in Pipfile.lock is invalid and will be ignored. http://vercel.link/python-version`
3163
+ `Warning: Python version "${version2}" detected in ${source} is invalid and will be ignored. http://vercel.link/python-version`
3164
+ );
3165
+ console.log(
3166
+ `Falling back to latest installed version: ${selection.version}`
3084
3167
  );
3085
3168
  }
3169
+ } else {
3170
+ console.log(
3171
+ `No Python version specified in pyproject.toml or Pipfile.lock. Using latest installed version: ${selection.version}`
3172
+ );
3086
3173
  }
3087
3174
  if (isDiscontinued(selection)) {
3088
3175
  throw new import_build_utils2.NowBuildError({
3089
3176
  code: "BUILD_UTILS_PYTHON_VERSION_DISCONTINUED",
3090
3177
  link: "http://vercel.link/python-version",
3091
- message: `Python version "${selection.version}" detected in Pipfile.lock is discontinued and must be upgraded.`
3178
+ message: `Python version "${selection.version}" declared in project configuration is discontinued and must be upgraded.`
3092
3179
  });
3093
3180
  }
3094
3181
  if (selection.discontinueDate) {
3095
3182
  const d = selection.discontinueDate.toISOString().split("T")[0];
3183
+ const srcSuffix = declaredPythonVersion ? `detected in ${declaredPythonVersion.source}` : "selected by runtime";
3096
3184
  console.warn(
3097
- `Error: Python version "${selection.version}" detected in Pipfile.lock has reached End-of-Life. Deployments created on or after ${d} will fail to build. http://vercel.link/python-version`
3185
+ `Error: Python version "${selection.version}" ${srcSuffix} has reached End-of-Life. Deployments created on or after ${d} will fail to build. http://vercel.link/python-version`
3098
3186
  );
3099
3187
  }
3100
3188
  return selection;
@@ -3107,14 +3195,23 @@ function isInstalled2({ pipPath, pythonPath }) {
3107
3195
  return Boolean(import_which2.default.sync(pipPath, { nothrow: true })) && Boolean(import_which2.default.sync(pythonPath, { nothrow: true }));
3108
3196
  }
3109
3197
 
3110
- // src/index.ts
3111
- var readFile = (0, import_util.promisify)(import_fs2.default.readFile);
3112
- var writeFile = (0, import_util.promisify)(import_fs2.default.writeFile);
3113
- var fastapiEntrypointFilenames = ["app", "index", "server", "main"];
3114
- var fastapiEntrypointDirs = ["", "src", "app"];
3115
- var fastapiContentRegex = /(from\s+fastapi\s+import\s+FastAPI|import\s+fastapi|FastAPI\s*\()/;
3116
- var fastapiCandidateEntrypoints = fastapiEntrypointFilenames.flatMap(
3117
- (filename) => fastapiEntrypointDirs.map((dir) => import_path2.posix.join(dir, `${filename}.py`))
3198
+ // src/start-dev-server.ts
3199
+ var import_child_process2 = require("child_process");
3200
+ var import_fs4 = require("fs");
3201
+ var import_path4 = require("path");
3202
+ var import_build_utils4 = require("@vercel/build-utils");
3203
+
3204
+ // src/entrypoint.ts
3205
+ var import_fs2 = __toESM(require("fs"));
3206
+ var import_path2 = require("path");
3207
+ var import_build_utils3 = require("@vercel/build-utils");
3208
+ var FASTAPI_ENTRYPOINT_FILENAMES = ["app", "index", "server", "main"];
3209
+ var FASTAPI_ENTRYPOINT_DIRS = ["", "src", "app"];
3210
+ var FASTAPI_CONTENT_REGEX = /(from\s+fastapi\s+import\s+FastAPI|import\s+fastapi|FastAPI\s*\()/;
3211
+ var FASTAPI_CANDIDATE_ENTRYPOINTS = FASTAPI_ENTRYPOINT_FILENAMES.flatMap(
3212
+ (filename) => FASTAPI_ENTRYPOINT_DIRS.map(
3213
+ (dir) => import_path2.posix.join(dir, `${filename}.py`)
3214
+ )
3118
3215
  );
3119
3216
  function isFastapiEntrypoint(file) {
3120
3217
  try {
@@ -3122,39 +3219,391 @@ function isFastapiEntrypoint(file) {
3122
3219
  if (!fsPath)
3123
3220
  return false;
3124
3221
  const contents = import_fs2.default.readFileSync(fsPath, "utf8");
3125
- return fastapiContentRegex.test(contents);
3222
+ return FASTAPI_CONTENT_REGEX.test(contents);
3126
3223
  } catch {
3127
3224
  return false;
3128
3225
  }
3129
3226
  }
3130
- async function pipenvConvert(cmd, srcDir, env) {
3131
- (0, import_build_utils3.debug)("Running pipfile2req...");
3227
+ async function detectFastapiEntrypoint(workPath, configuredEntrypoint) {
3228
+ const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
3132
3229
  try {
3133
- const out = await import_execa2.default.stdout(cmd, [], {
3134
- cwd: srcDir,
3135
- env
3230
+ const fsFiles = await (0, import_build_utils3.glob)("**", workPath);
3231
+ if (fsFiles[entry])
3232
+ return entry;
3233
+ const candidates = FASTAPI_CANDIDATE_ENTRYPOINTS.filter(
3234
+ (c) => !!fsFiles[c]
3235
+ );
3236
+ if (candidates.length > 0) {
3237
+ const fastapiEntrypoint = candidates.find(
3238
+ (c) => isFastapiEntrypoint(fsFiles[c])
3239
+ ) || candidates[0];
3240
+ (0, import_build_utils3.debug)(`Detected FastAPI entrypoint: ${fastapiEntrypoint}`);
3241
+ return fastapiEntrypoint;
3242
+ }
3243
+ return null;
3244
+ } catch {
3245
+ (0, import_build_utils3.debug)("Failed to discover entrypoint for FastAPI");
3246
+ return null;
3247
+ }
3248
+ }
3249
+
3250
+ // src/utils.ts
3251
+ var import_child_process = require("child_process");
3252
+ var import_fs3 = __toESM(require("fs"));
3253
+ var import_path3 = require("path");
3254
+ var tryImport = (pythonPath, mod) => new Promise((res) => {
3255
+ const check = (0, import_child_process.spawn)(pythonPath, ["-c", `import ${mod}`], {
3256
+ stdio: ["ignore", "pipe", "pipe"]
3257
+ });
3258
+ check.once("error", () => res(false));
3259
+ check.once("exit", (code) => res(code === 0));
3260
+ });
3261
+ var detectAsgiServer = async (workPath, pythonPath) => new Promise((resolve, reject) => {
3262
+ tryImport(pythonPath, "uvicorn").then((hasUvicorn) => {
3263
+ if (hasUvicorn)
3264
+ return resolve("uvicorn");
3265
+ tryImport(pythonPath, "hypercorn").then((hasHypercorn) => {
3266
+ if (hasHypercorn)
3267
+ return resolve("hypercorn");
3268
+ const { venvRoot } = useVirtualEnv(workPath, {}, pythonPath);
3269
+ const baseErrorMessage = 'No ASGI server found. Please install either "uvicorn" or "hypercorn" (e.g. "pip install uvicorn").';
3270
+ const errorMessage = !venvRoot ? `${baseErrorMessage} If you are using a virtual environment, please activate it and try again.` : baseErrorMessage;
3271
+ reject(new Error(errorMessage));
3136
3272
  });
3137
- (0, import_build_utils3.debug)("Contents of requirements.txt is: " + out);
3138
- import_fs2.default.writeFileSync((0, import_path2.join)(srcDir, "requirements.txt"), out);
3273
+ });
3274
+ });
3275
+ var isInVirtualEnv = () => {
3276
+ return process.env.VIRTUAL_ENV;
3277
+ };
3278
+ function useVirtualEnv(workPath, env, systemPython) {
3279
+ const venvDirs = [".venv", "venv"];
3280
+ let pythonCmd = systemPython;
3281
+ for (const venv of venvDirs) {
3282
+ const venvRoot = (0, import_path3.join)(workPath, venv);
3283
+ const binDir = process.platform === "win32" ? (0, import_path3.join)(venvRoot, "Scripts") : (0, import_path3.join)(venvRoot, "bin");
3284
+ 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")];
3285
+ const found = candidates.find((p) => import_fs3.default.existsSync(p));
3286
+ if (found) {
3287
+ pythonCmd = found;
3288
+ env.VIRTUAL_ENV = venvRoot;
3289
+ env.PATH = `${binDir}${import_path3.delimiter}${env.PATH || ""}`;
3290
+ return { pythonCmd, venvRoot };
3291
+ }
3292
+ }
3293
+ return { pythonCmd };
3294
+ }
3295
+
3296
+ // src/start-dev-server.ts
3297
+ function silenceNodeWarnings() {
3298
+ const original = process.emitWarning.bind(
3299
+ process
3300
+ );
3301
+ let active = true;
3302
+ const wrapped = (warning, ...args) => {
3303
+ if (!active) {
3304
+ return original(
3305
+ warning,
3306
+ ...args
3307
+ );
3308
+ }
3309
+ return;
3310
+ };
3311
+ process.emitWarning = wrapped;
3312
+ return () => {
3313
+ if (!active)
3314
+ return;
3315
+ active = false;
3316
+ if (process.emitWarning === wrapped) {
3317
+ process.emitWarning = original;
3318
+ }
3319
+ };
3320
+ }
3321
+ var ANSI_PATTERN = "[\\u001B\\u009B][[\\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nq-uy=><]";
3322
+ var ANSI_ESCAPE_RE = new RegExp(ANSI_PATTERN, "g");
3323
+ var stripAnsi = (s) => s.replace(ANSI_ESCAPE_RE, "");
3324
+ var ASGI_SHIM_MODULE = "vc_init_dev_asgi";
3325
+ var PERSISTENT_SERVERS = /* @__PURE__ */ new Map();
3326
+ var PENDING_STARTS = /* @__PURE__ */ new Map();
3327
+ var restoreWarnings = null;
3328
+ var cleanupHandlersInstalled = false;
3329
+ function installGlobalCleanupHandlers() {
3330
+ if (cleanupHandlersInstalled)
3331
+ return;
3332
+ cleanupHandlersInstalled = true;
3333
+ const killAll = () => {
3334
+ for (const [key, info] of PERSISTENT_SERVERS.entries()) {
3335
+ try {
3336
+ process.kill(info.pid, "SIGTERM");
3337
+ } catch (err) {
3338
+ (0, import_build_utils4.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
3339
+ }
3340
+ try {
3341
+ process.kill(info.pid, "SIGKILL");
3342
+ } catch (err) {
3343
+ (0, import_build_utils4.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
3344
+ }
3345
+ PERSISTENT_SERVERS.delete(key);
3346
+ }
3347
+ if (restoreWarnings) {
3348
+ try {
3349
+ restoreWarnings();
3350
+ } catch (err) {
3351
+ (0, import_build_utils4.debug)(`Error restoring warnings: ${err}`);
3352
+ }
3353
+ restoreWarnings = null;
3354
+ }
3355
+ };
3356
+ process.on("SIGINT", () => {
3357
+ killAll();
3358
+ process.exit(130);
3359
+ });
3360
+ process.on("SIGTERM", () => {
3361
+ killAll();
3362
+ process.exit(143);
3363
+ });
3364
+ process.on("exit", () => {
3365
+ killAll();
3366
+ });
3367
+ }
3368
+ function createDevStaticShim(workPath, modulePath) {
3369
+ try {
3370
+ const vercelPythonDir = (0, import_path4.join)(workPath, ".vercel", "python");
3371
+ (0, import_fs4.mkdirSync)(vercelPythonDir, { recursive: true });
3372
+ const shimPath = (0, import_path4.join)(vercelPythonDir, `${ASGI_SHIM_MODULE}.py`);
3373
+ const templatePath = (0, import_path4.join)(__dirname, "..", `${ASGI_SHIM_MODULE}.py`);
3374
+ const template = (0, import_fs4.readFileSync)(templatePath, "utf8");
3375
+ const shimSource = template.replace(/__VC_DEV_MODULE_PATH__/g, modulePath);
3376
+ (0, import_fs4.writeFileSync)(shimPath, shimSource, "utf8");
3377
+ (0, import_build_utils4.debug)(`Prepared Python dev static shim at ${shimPath}`);
3378
+ return ASGI_SHIM_MODULE;
3139
3379
  } catch (err) {
3140
- console.log('Failed to run "pipfile2req"');
3141
- throw err;
3380
+ (0, import_build_utils4.debug)(`Failed to prepare dev static shim: ${err?.message || err}`);
3381
+ return null;
3142
3382
  }
3143
3383
  }
3384
+ var startDevServer = async (opts) => {
3385
+ const { entrypoint: rawEntrypoint, workPath, meta = {}, config } = opts;
3386
+ if (config?.framework !== "fastapi") {
3387
+ return null;
3388
+ }
3389
+ if (!restoreWarnings)
3390
+ restoreWarnings = silenceNodeWarnings();
3391
+ installGlobalCleanupHandlers();
3392
+ const detected = await detectFastapiEntrypoint(workPath, rawEntrypoint);
3393
+ if (!detected) {
3394
+ throw new Error(
3395
+ `No FastAPI entrypoint found. Searched for: ${FASTAPI_CANDIDATE_ENTRYPOINTS.join(", ")}`
3396
+ );
3397
+ }
3398
+ const entry = detected;
3399
+ const modulePath = entry.replace(/\.py$/i, "").replace(/[\\/]/g, ".");
3400
+ const env = { ...process.env, ...meta.env || {} };
3401
+ const serverKey = `${workPath}::${entry}`;
3402
+ const existing = PERSISTENT_SERVERS.get(serverKey);
3403
+ if (existing) {
3404
+ return {
3405
+ port: existing.port,
3406
+ pid: existing.pid,
3407
+ shutdown: async () => {
3408
+ }
3409
+ };
3410
+ }
3411
+ {
3412
+ const pending = PENDING_STARTS.get(serverKey);
3413
+ if (pending) {
3414
+ const { port, pid } = await pending;
3415
+ return {
3416
+ port,
3417
+ pid,
3418
+ shutdown: async () => {
3419
+ }
3420
+ };
3421
+ }
3422
+ }
3423
+ let childProcess = null;
3424
+ let stdoutLogListener = null;
3425
+ let stderrLogListener = null;
3426
+ let resolveChildReady;
3427
+ let rejectChildReady;
3428
+ const childReady = new Promise(
3429
+ (resolve, reject) => {
3430
+ resolveChildReady = resolve;
3431
+ rejectChildReady = reject;
3432
+ }
3433
+ );
3434
+ PENDING_STARTS.set(serverKey, childReady);
3435
+ try {
3436
+ await new Promise((resolve, reject) => {
3437
+ let resolved = false;
3438
+ const { pythonPath: systemPython } = getLatestPythonVersion(meta);
3439
+ let pythonCmd = systemPython;
3440
+ const venv = isInVirtualEnv();
3441
+ if (venv) {
3442
+ (0, import_build_utils4.debug)(`Running in virtualenv at ${venv}`);
3443
+ } else {
3444
+ const { pythonCmd: venvPythonCmd, venvRoot } = useVirtualEnv(
3445
+ workPath,
3446
+ env,
3447
+ systemPython
3448
+ );
3449
+ pythonCmd = venvPythonCmd;
3450
+ if (venvRoot) {
3451
+ (0, import_build_utils4.debug)(`Using virtualenv at ${venvRoot}`);
3452
+ } else {
3453
+ (0, import_build_utils4.debug)("No virtualenv found");
3454
+ }
3455
+ }
3456
+ const devShimModule = createDevStaticShim(workPath, modulePath);
3457
+ if (devShimModule) {
3458
+ const vercelPythonDir = (0, import_path4.join)(workPath, ".vercel", "python");
3459
+ const existingPythonPath = env.PYTHONPATH || "";
3460
+ env.PYTHONPATH = existingPythonPath ? `${vercelPythonDir}:${existingPythonPath}` : vercelPythonDir;
3461
+ }
3462
+ detectAsgiServer(workPath, pythonCmd).then(async (serverKind) => {
3463
+ if (resolved)
3464
+ return;
3465
+ const host = "127.0.0.1";
3466
+ const argv = serverKind === "uvicorn" ? [
3467
+ "-u",
3468
+ "-m",
3469
+ "uvicorn",
3470
+ `${devShimModule || modulePath}:app`,
3471
+ "--host",
3472
+ host,
3473
+ "--port",
3474
+ "0",
3475
+ "--use-colors"
3476
+ ] : [
3477
+ "-u",
3478
+ "-m",
3479
+ "hypercorn",
3480
+ `${devShimModule || modulePath}:app`,
3481
+ "-b",
3482
+ `${host}:0`
3483
+ ];
3484
+ (0, import_build_utils4.debug)(
3485
+ `Starting dev server (${serverKind}): ${pythonCmd} ${argv.join(" ")}`
3486
+ );
3487
+ const child = (0, import_child_process2.spawn)(pythonCmd, argv, {
3488
+ cwd: workPath,
3489
+ env,
3490
+ stdio: ["inherit", "pipe", "pipe"]
3491
+ });
3492
+ childProcess = child;
3493
+ stdoutLogListener = (buf) => {
3494
+ const s = buf.toString();
3495
+ for (const line of s.split(/\r?\n/)) {
3496
+ if (line) {
3497
+ process.stdout.write(line.endsWith("\n") ? line : line + "\n");
3498
+ }
3499
+ }
3500
+ };
3501
+ stderrLogListener = (buf) => {
3502
+ const s = buf.toString();
3503
+ for (const line of s.split(/\r?\n/)) {
3504
+ if (line) {
3505
+ process.stderr.write(line.endsWith("\n") ? line : line + "\n");
3506
+ }
3507
+ }
3508
+ };
3509
+ child.stdout?.on("data", stdoutLogListener);
3510
+ child.stderr?.on("data", stderrLogListener);
3511
+ const readinessRegexes = [
3512
+ /Uvicorn running on https?:\/\/(?:\[[^\]]+\]|[^:]+):(\d+)/i,
3513
+ /Hypercorn running on https?:\/\/(?:\[[^\]]+\]|[^:]+):(\d+)/i,
3514
+ /(?:Running|Serving) on https?:\/\/(?:\[[^\]]+\]|[^:\s]+):(\d+)/i
3515
+ ];
3516
+ const onDetect = (chunk) => {
3517
+ const text = chunk.toString();
3518
+ const clean = stripAnsi(text);
3519
+ let portMatch = null;
3520
+ for (const rx of readinessRegexes) {
3521
+ const m = clean.match(rx);
3522
+ if (m) {
3523
+ portMatch = m;
3524
+ break;
3525
+ }
3526
+ }
3527
+ if (portMatch && child.pid) {
3528
+ if (!resolved) {
3529
+ resolved = true;
3530
+ child.stdout?.removeListener("data", onDetect);
3531
+ child.stderr?.removeListener("data", onDetect);
3532
+ const port2 = Number(portMatch[1]);
3533
+ resolveChildReady({ port: port2, pid: child.pid });
3534
+ resolve();
3535
+ }
3536
+ }
3537
+ };
3538
+ child.stdout?.on("data", onDetect);
3539
+ child.stderr?.on("data", onDetect);
3540
+ child.once("error", (err) => {
3541
+ if (!resolved) {
3542
+ rejectChildReady(err);
3543
+ reject(err);
3544
+ }
3545
+ });
3546
+ child.once("exit", (code, signal) => {
3547
+ if (!resolved) {
3548
+ const err = new Error(
3549
+ `${serverKind} server exited before binding (code=${code}, signal=${signal})`
3550
+ );
3551
+ rejectChildReady(err);
3552
+ reject(err);
3553
+ }
3554
+ });
3555
+ }).catch((err) => {
3556
+ rejectChildReady(err);
3557
+ reject(err);
3558
+ });
3559
+ });
3560
+ const { port, pid } = await childReady;
3561
+ PERSISTENT_SERVERS.set(serverKey, {
3562
+ port,
3563
+ pid,
3564
+ child: childProcess,
3565
+ stdoutLogListener,
3566
+ stderrLogListener
3567
+ });
3568
+ const shutdown = async () => {
3569
+ };
3570
+ return { port, pid, shutdown };
3571
+ } finally {
3572
+ PENDING_STARTS.delete(serverKey);
3573
+ }
3574
+ };
3575
+
3576
+ // src/index.ts
3577
+ var readFile = (0, import_util.promisify)(import_fs5.default.readFile);
3578
+ var writeFile = (0, import_util.promisify)(import_fs5.default.writeFile);
3144
3579
  var version = 3;
3580
+ function findDir({
3581
+ file,
3582
+ entryDirectory,
3583
+ workPath,
3584
+ fsFiles
3585
+ }) {
3586
+ if (fsFiles[(0, import_path5.join)(entryDirectory, file)]) {
3587
+ return (0, import_path5.join)(workPath, entryDirectory);
3588
+ }
3589
+ if (fsFiles[file]) {
3590
+ return workPath;
3591
+ }
3592
+ return null;
3593
+ }
3145
3594
  async function downloadFilesInWorkPath({
3146
3595
  entrypoint,
3147
3596
  workPath,
3148
3597
  files,
3149
3598
  meta = {}
3150
3599
  }) {
3151
- (0, import_build_utils3.debug)("Downloading user files...");
3152
- let downloadedFiles = await (0, import_build_utils3.download)(files, workPath, meta);
3600
+ (0, import_build_utils5.debug)("Downloading user files...");
3601
+ let downloadedFiles = await (0, import_build_utils5.download)(files, workPath, meta);
3153
3602
  if (meta.isDev) {
3154
- const { devCacheDir = (0, import_path2.join)(workPath, ".now", "cache") } = meta;
3155
- const destCache = (0, import_path2.join)(devCacheDir, (0, import_path2.basename)(entrypoint, ".py"));
3156
- await (0, import_build_utils3.download)(downloadedFiles, destCache);
3157
- downloadedFiles = await (0, import_build_utils3.glob)("**", destCache);
3603
+ const { devCacheDir = (0, import_path5.join)(workPath, ".now", "cache") } = meta;
3604
+ const destCache = (0, import_path5.join)(devCacheDir, (0, import_path5.basename)(entrypoint, ".py"));
3605
+ await (0, import_build_utils5.download)(downloadedFiles, destCache);
3606
+ downloadedFiles = await (0, import_build_utils5.glob)("**", destCache);
3158
3607
  workPath = destCache;
3159
3608
  }
3160
3609
  return workPath;
@@ -3166,7 +3615,6 @@ var build = async ({
3166
3615
  meta = {},
3167
3616
  config
3168
3617
  }) => {
3169
- let pythonVersion = getLatestPythonVersion(meta);
3170
3618
  workPath = await downloadFilesInWorkPath({
3171
3619
  workPath,
3172
3620
  files: originalFiles,
@@ -3175,98 +3623,91 @@ var build = async ({
3175
3623
  });
3176
3624
  try {
3177
3625
  if (meta.isDev) {
3178
- const setupCfg = (0, import_path2.join)(workPath, "setup.cfg");
3626
+ const setupCfg = (0, import_path5.join)(workPath, "setup.cfg");
3179
3627
  await writeFile(setupCfg, "[install]\nprefix=\n");
3180
3628
  }
3181
3629
  } catch (err) {
3182
3630
  console.log('Failed to create "setup.cfg" file');
3183
3631
  throw err;
3184
3632
  }
3185
- let fsFiles = await (0, import_build_utils3.glob)("**", workPath);
3186
- if (!fsFiles[entrypoint]) {
3187
- let discovered;
3188
- if (config?.framework === "fastapi") {
3189
- const entrypointCandidates = fastapiCandidateEntrypoints.filter(
3190
- (c) => !!fsFiles[c]
3633
+ let fsFiles = await (0, import_build_utils5.glob)("**", workPath);
3634
+ if (!fsFiles[entrypoint] && config?.framework === "fastapi") {
3635
+ const detected = await detectFastapiEntrypoint(workPath, entrypoint);
3636
+ if (detected) {
3637
+ (0, import_build_utils5.debug)(
3638
+ `Resolved Python entrypoint to "${detected}" (configured "${entrypoint}" not found).`
3191
3639
  );
3192
- if (entrypointCandidates.length) {
3193
- const fastapiEntrypoint = entrypointCandidates.find(
3194
- (c) => isFastapiEntrypoint(fsFiles[c])
3195
- );
3196
- discovered = fastapiEntrypoint || entrypointCandidates[0];
3197
- }
3198
- }
3199
- if (discovered) {
3200
- (0, import_build_utils3.debug)(
3201
- `Resolved Python entrypoint to "${discovered}" (configured "${entrypoint}" not found).`
3202
- );
3203
- entrypoint = discovered;
3204
- } else if (config?.framework === "fastapi") {
3205
- const searchedList = fastapiCandidateEntrypoints.join(", ");
3206
- throw new import_build_utils3.NowBuildError({
3640
+ entrypoint = detected;
3641
+ } else {
3642
+ const searchedList = FASTAPI_CANDIDATE_ENTRYPOINTS.join(", ");
3643
+ throw new import_build_utils5.NowBuildError({
3207
3644
  code: "FASTAPI_ENTRYPOINT_NOT_FOUND",
3208
3645
  message: `No FastAPI entrypoint found. Searched for: ${searchedList}`
3209
3646
  });
3210
3647
  }
3211
3648
  }
3212
- const entryDirectory = (0, import_path2.dirname)(entrypoint);
3213
- const hasReqLocal = !!fsFiles[(0, import_path2.join)(entryDirectory, "requirements.txt")];
3649
+ const entryDirectory = (0, import_path5.dirname)(entrypoint);
3650
+ const hasReqLocal = !!fsFiles[(0, import_path5.join)(entryDirectory, "requirements.txt")];
3214
3651
  const hasReqGlobal = !!fsFiles["requirements.txt"];
3215
- const pipfileLockDir = fsFiles[(0, import_path2.join)(entryDirectory, "Pipfile.lock")] ? (0, import_path2.join)(workPath, entryDirectory) : fsFiles["Pipfile.lock"] ? workPath : null;
3216
- const pipfileDir = fsFiles[(0, import_path2.join)(entryDirectory, "Pipfile")] ? (0, import_path2.join)(workPath, entryDirectory) : fsFiles["Pipfile"] ? workPath : null;
3217
- if (!hasReqLocal && !hasReqGlobal && (pipfileLockDir || pipfileDir)) {
3218
- if (pipfileLockDir) {
3219
- (0, import_build_utils3.debug)('Found "Pipfile.lock"');
3220
- } else {
3221
- (0, import_build_utils3.debug)('Found "Pipfile"');
3652
+ const uvLockDir = findDir({
3653
+ file: "uv.lock",
3654
+ entryDirectory,
3655
+ workPath,
3656
+ fsFiles
3657
+ });
3658
+ const pyprojectDir = findDir({
3659
+ file: "pyproject.toml",
3660
+ entryDirectory,
3661
+ workPath,
3662
+ fsFiles
3663
+ });
3664
+ const pipfileLockDir = fsFiles[(0, import_path5.join)(entryDirectory, "Pipfile.lock")] ? (0, import_path5.join)(workPath, entryDirectory) : fsFiles["Pipfile.lock"] ? workPath : null;
3665
+ const pipfileDir = fsFiles[(0, import_path5.join)(entryDirectory, "Pipfile")] ? (0, import_path5.join)(workPath, entryDirectory) : fsFiles["Pipfile"] ? workPath : null;
3666
+ let declaredPythonVersion;
3667
+ if (pyprojectDir) {
3668
+ let requiresPython;
3669
+ try {
3670
+ const pyproject = await (0, import_build_utils6.readConfigFile)((0, import_path5.join)(pyprojectDir, "pyproject.toml"));
3671
+ requiresPython = pyproject?.project?.["requires-python"];
3672
+ } catch (err) {
3673
+ (0, import_build_utils5.debug)("Failed to parse pyproject.toml", err);
3674
+ }
3675
+ const VERSION_REGEX = /\b\d+\.\d+\b/;
3676
+ const exact = requiresPython?.trim().match(VERSION_REGEX)?.[0];
3677
+ if (exact) {
3678
+ declaredPythonVersion = { version: exact, source: "pyproject.toml" };
3679
+ (0, import_build_utils5.debug)(
3680
+ `Found Python version ${exact} in pyproject.toml (requires-python: "${requiresPython}")`
3681
+ );
3682
+ } else if (requiresPython) {
3683
+ (0, import_build_utils5.debug)(
3684
+ `Could not parse Python version from pyproject.toml requires-python: "${requiresPython}"`
3685
+ );
3222
3686
  }
3223
- if (pipfileLockDir) {
3224
- let lock = {};
3225
- try {
3226
- const json = await readFile(
3227
- (0, import_path2.join)(pipfileLockDir, "Pipfile.lock"),
3228
- "utf8"
3229
- );
3230
- lock = JSON.parse(json);
3231
- } catch (err) {
3232
- throw new import_build_utils3.NowBuildError({
3233
- code: "INVALID_PIPFILE_LOCK",
3234
- message: "Unable to parse Pipfile.lock"
3235
- });
3236
- }
3237
- pythonVersion = getSupportedPythonVersion({
3238
- isDev: meta.isDev,
3239
- pipLockPythonVersion: lock?._meta?.requires?.python_version
3687
+ } else if (pipfileLockDir) {
3688
+ let lock = {};
3689
+ try {
3690
+ const json = await readFile((0, import_path5.join)(pipfileLockDir, "Pipfile.lock"), "utf8");
3691
+ lock = JSON.parse(json);
3692
+ } catch (err) {
3693
+ throw new import_build_utils5.NowBuildError({
3694
+ code: "INVALID_PIPFILE_LOCK",
3695
+ message: "Unable to parse Pipfile.lock"
3240
3696
  });
3241
3697
  }
3242
- if (!hasReqLocal && !hasReqGlobal) {
3243
- const tempDir = await (0, import_build_utils3.getWriteableDirectory)();
3244
- await installRequirement({
3245
- pythonPath: pythonVersion.pythonPath,
3246
- pipPath: pythonVersion.pipPath,
3247
- dependency: "pipfile-requirements",
3248
- version: "0.3.0",
3249
- workPath: tempDir,
3250
- meta,
3251
- args: ["--no-warn-script-location"]
3252
- });
3253
- const tempVendorDir = (0, import_path2.join)(tempDir, resolveVendorDir());
3254
- const envForConvert = { ...process.env, PYTHONPATH: tempVendorDir };
3255
- const convertCmd = process.platform === "win32" ? (0, import_path2.join)(tempVendorDir, "Scripts", "pipfile2req.exe") : (0, import_path2.join)(tempVendorDir, "bin", "pipfile2req");
3256
- await pipenvConvert(
3257
- convertCmd,
3258
- pipfileLockDir || pipfileDir,
3259
- envForConvert
3260
- );
3261
- } else {
3262
- (0, import_build_utils3.debug)(
3263
- 'Skipping Pipfile.lock conversion because "requirements.txt" exists'
3264
- );
3698
+ const pyFromLock = lock?._meta?.requires?.python_version;
3699
+ if (pyFromLock) {
3700
+ declaredPythonVersion = { version: pyFromLock, source: "Pipfile.lock" };
3701
+ (0, import_build_utils5.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
3265
3702
  }
3266
3703
  }
3267
- fsFiles = await (0, import_build_utils3.glob)("**", workPath);
3268
- const requirementsTxt = (0, import_path2.join)(entryDirectory, "requirements.txt");
3269
- const vendorBaseDir = (0, import_path2.join)(
3704
+ const pythonVersion = getSupportedPythonVersion({
3705
+ isDev: meta.isDev,
3706
+ declaredPythonVersion
3707
+ });
3708
+ fsFiles = await (0, import_build_utils5.glob)("**", workPath);
3709
+ const requirementsTxt = (0, import_path5.join)(entryDirectory, "requirements.txt");
3710
+ const vendorBaseDir = (0, import_path5.join)(
3270
3711
  workPath,
3271
3712
  ".vercel",
3272
3713
  "python",
@@ -3274,49 +3715,150 @@ var build = async ({
3274
3715
  entryDirectory
3275
3716
  );
3276
3717
  try {
3277
- await import_fs2.default.promises.mkdir(vendorBaseDir, { recursive: true });
3718
+ await import_fs5.default.promises.mkdir(vendorBaseDir, { recursive: true });
3278
3719
  } catch (err) {
3279
3720
  console.log("Failed to create vendor cache directory");
3280
3721
  throw err;
3281
3722
  }
3282
- console.log("Installing required dependencies...");
3723
+ let installationSource;
3724
+ if (uvLockDir && pyprojectDir) {
3725
+ installationSource = "uv.lock";
3726
+ } else if (pyprojectDir) {
3727
+ installationSource = "pyproject.toml";
3728
+ } else if (pipfileLockDir) {
3729
+ installationSource = "Pipfile.lock";
3730
+ } else if (pipfileDir) {
3731
+ installationSource = "Pipfile";
3732
+ } else if (fsFiles[requirementsTxt] || fsFiles["requirements.txt"]) {
3733
+ installationSource = "requirements.txt";
3734
+ }
3735
+ if (installationSource) {
3736
+ console.log(
3737
+ `Installing required dependencies from ${installationSource}...`
3738
+ );
3739
+ } else {
3740
+ console.log("Installing required dependencies...");
3741
+ }
3742
+ let uvPath = null;
3743
+ try {
3744
+ uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
3745
+ console.log(`Using uv at "${uvPath}"`);
3746
+ } catch (err) {
3747
+ if (uvLockDir || pyprojectDir && !hasReqLocal && !hasReqGlobal) {
3748
+ console.log("Failed to install uv");
3749
+ throw new Error(
3750
+ `uv is required for this project but failed to install: ${err instanceof Error ? err.message : String(err)}`
3751
+ );
3752
+ }
3753
+ (0, import_build_utils5.debug)("Failed to install uv", err);
3754
+ }
3283
3755
  await installRequirement({
3284
3756
  pythonPath: pythonVersion.pythonPath,
3285
3757
  pipPath: pythonVersion.pipPath,
3758
+ uvPath,
3286
3759
  dependency: "werkzeug",
3287
3760
  version: "1.0.1",
3288
- workPath: vendorBaseDir,
3761
+ workPath,
3762
+ targetDir: vendorBaseDir,
3289
3763
  meta
3290
3764
  });
3291
- if (fsFiles[requirementsTxt]) {
3292
- (0, import_build_utils3.debug)('Found local "requirements.txt"');
3765
+ let installedFromProjectFiles = false;
3766
+ if (uvLockDir) {
3767
+ (0, import_build_utils5.debug)('Found "uv.lock"');
3768
+ if (pyprojectDir) {
3769
+ const exportedReq = await exportRequirementsFromUv(pyprojectDir, uvPath, {
3770
+ locked: true
3771
+ });
3772
+ await installRequirementsFile({
3773
+ pythonPath: pythonVersion.pythonPath,
3774
+ pipPath: pythonVersion.pipPath,
3775
+ uvPath,
3776
+ filePath: exportedReq,
3777
+ workPath,
3778
+ targetDir: vendorBaseDir,
3779
+ meta
3780
+ });
3781
+ installedFromProjectFiles = true;
3782
+ } else {
3783
+ (0, import_build_utils5.debug)('Skipping uv export because "pyproject.toml" was not found');
3784
+ }
3785
+ } else if (pyprojectDir) {
3786
+ (0, import_build_utils5.debug)('Found "pyproject.toml"');
3787
+ if (hasReqLocal || hasReqGlobal) {
3788
+ console.log(
3789
+ "Detected both pyproject.toml and requirements.txt but no lockfile; using pyproject.toml"
3790
+ );
3791
+ }
3792
+ const exportedReq = await exportRequirementsFromUv(pyprojectDir, uvPath, {
3793
+ locked: false
3794
+ });
3795
+ await installRequirementsFile({
3796
+ pythonPath: pythonVersion.pythonPath,
3797
+ pipPath: pythonVersion.pipPath,
3798
+ uvPath,
3799
+ filePath: exportedReq,
3800
+ workPath,
3801
+ targetDir: vendorBaseDir,
3802
+ meta
3803
+ });
3804
+ installedFromProjectFiles = true;
3805
+ } else if (pipfileLockDir || pipfileDir) {
3806
+ (0, import_build_utils5.debug)(`Found ${pipfileLockDir ? '"Pipfile.lock"' : '"Pipfile"'}`);
3807
+ if (hasReqLocal || hasReqGlobal) {
3808
+ (0, import_build_utils5.debug)('Skipping Pipfile export because "requirements.txt" exists');
3809
+ } else {
3810
+ const exportedReq = await exportRequirementsFromPipfile({
3811
+ pythonPath: pythonVersion.pythonPath,
3812
+ pipPath: pythonVersion.pipPath,
3813
+ uvPath,
3814
+ projectDir: pipfileLockDir || pipfileDir,
3815
+ meta
3816
+ });
3817
+ await installRequirementsFile({
3818
+ pythonPath: pythonVersion.pythonPath,
3819
+ pipPath: pythonVersion.pipPath,
3820
+ uvPath,
3821
+ filePath: exportedReq,
3822
+ workPath,
3823
+ targetDir: vendorBaseDir,
3824
+ meta
3825
+ });
3826
+ installedFromProjectFiles = true;
3827
+ }
3828
+ }
3829
+ if (!installedFromProjectFiles && fsFiles[requirementsTxt]) {
3830
+ (0, import_build_utils5.debug)('Found local "requirements.txt"');
3293
3831
  const requirementsTxtPath = fsFiles[requirementsTxt].fsPath;
3294
3832
  await installRequirementsFile({
3295
3833
  pythonPath: pythonVersion.pythonPath,
3296
3834
  pipPath: pythonVersion.pipPath,
3835
+ uvPath,
3297
3836
  filePath: requirementsTxtPath,
3298
- workPath: vendorBaseDir,
3837
+ workPath,
3838
+ targetDir: vendorBaseDir,
3299
3839
  meta
3300
3840
  });
3301
- } else if (fsFiles["requirements.txt"]) {
3302
- (0, import_build_utils3.debug)('Found global "requirements.txt"');
3841
+ } else if (!installedFromProjectFiles && fsFiles["requirements.txt"]) {
3842
+ (0, import_build_utils5.debug)('Found global "requirements.txt"');
3303
3843
  const requirementsTxtPath = fsFiles["requirements.txt"].fsPath;
3304
3844
  await installRequirementsFile({
3305
3845
  pythonPath: pythonVersion.pythonPath,
3306
3846
  pipPath: pythonVersion.pipPath,
3847
+ uvPath,
3307
3848
  filePath: requirementsTxtPath,
3308
- workPath: vendorBaseDir,
3849
+ workPath,
3850
+ targetDir: vendorBaseDir,
3309
3851
  meta
3310
3852
  });
3311
3853
  }
3312
- const originalPyPath = (0, import_path2.join)(__dirname, "..", "vc_init.py");
3854
+ const originalPyPath = (0, import_path5.join)(__dirname, "..", "vc_init.py");
3313
3855
  const originalHandlerPyContents = await readFile(originalPyPath, "utf8");
3314
- (0, import_build_utils3.debug)("Entrypoint is", entrypoint);
3315
- const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/, "");
3856
+ (0, import_build_utils5.debug)("Entrypoint is", entrypoint);
3857
+ const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
3316
3858
  const vendorDir = resolveVendorDir();
3317
3859
  const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
3318
3860
  const entrypointWithSuffix = `${entrypoint}${suffix}`;
3319
- (0, import_build_utils3.debug)("Entrypoint with suffix is", entrypointWithSuffix);
3861
+ (0, import_build_utils5.debug)("Entrypoint with suffix is", entrypointWithSuffix);
3320
3862
  const handlerPyContents = originalHandlerPyContents.replace(/__VC_HANDLER_MODULE_NAME/g, moduleName).replace(/__VC_HANDLER_ENTRYPOINT/g, entrypointWithSuffix).replace(/__VC_HANDLER_VENDOR_DIR/g, vendorDir);
3321
3863
  const predefinedExcludes = [
3322
3864
  ".git/**",
@@ -3328,7 +3870,8 @@ var build = async ({
3328
3870
  "**/.nuxt/**",
3329
3871
  "**/.venv/**",
3330
3872
  "**/venv/**",
3331
- "**/__pycache__/**"
3873
+ "**/__pycache__/**",
3874
+ "**/public/**"
3332
3875
  ];
3333
3876
  const lambdaEnv = {};
3334
3877
  lambdaEnv.PYTHONPATH = vendorDir;
@@ -3336,11 +3879,11 @@ var build = async ({
3336
3879
  cwd: workPath,
3337
3880
  ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
3338
3881
  };
3339
- const files = await (0, import_build_utils3.glob)("**", globOptions);
3882
+ const files = await (0, import_build_utils5.glob)("**", globOptions);
3340
3883
  try {
3341
- const cachedVendorAbs = (0, import_path2.join)(vendorBaseDir, resolveVendorDir());
3342
- if (import_fs2.default.existsSync(cachedVendorAbs)) {
3343
- const vendorFiles = await (0, import_build_utils3.glob)("**", cachedVendorAbs, resolveVendorDir());
3884
+ const cachedVendorAbs = (0, import_path5.join)(vendorBaseDir, resolveVendorDir());
3885
+ if (import_fs5.default.existsSync(cachedVendorAbs)) {
3886
+ const vendorFiles = await (0, import_build_utils5.glob)("**", cachedVendorAbs, resolveVendorDir());
3344
3887
  for (const [p, f] of Object.entries(vendorFiles)) {
3345
3888
  files[p] = f;
3346
3889
  }
@@ -3350,12 +3893,12 @@ var build = async ({
3350
3893
  throw err;
3351
3894
  }
3352
3895
  const handlerPyFilename = "vc__handler__python";
3353
- files[`${handlerPyFilename}.py`] = new import_build_utils3.FileBlob({ data: handlerPyContents });
3896
+ files[`${handlerPyFilename}.py`] = new import_build_utils5.FileBlob({ data: handlerPyContents });
3354
3897
  if (config.framework === "fasthtml") {
3355
3898
  const { SESSKEY = "" } = process.env;
3356
- files[".sesskey"] = new import_build_utils3.FileBlob({ data: `"${SESSKEY}"` });
3899
+ files[".sesskey"] = new import_build_utils5.FileBlob({ data: `"${SESSKEY}"` });
3357
3900
  }
3358
- const output = new import_build_utils3.Lambda({
3901
+ const output = new import_build_utils5.Lambda({
3359
3902
  files,
3360
3903
  handler: `${handlerPyFilename}.vc_handler`,
3361
3904
  runtime: pythonVersion.runtime,
@@ -3364,12 +3907,44 @@ var build = async ({
3364
3907
  });
3365
3908
  return { output };
3366
3909
  };
3910
+ var shouldServe = (opts) => {
3911
+ const framework = opts.config.framework;
3912
+ if (framework === "fastapi") {
3913
+ const requestPath = opts.requestPath.replace(/\/$/, "");
3914
+ if (requestPath.startsWith("api") && opts.hasMatched) {
3915
+ return false;
3916
+ }
3917
+ return true;
3918
+ }
3919
+ return defaultShouldServe(opts);
3920
+ };
3921
+ var defaultShouldServe = ({
3922
+ entrypoint,
3923
+ files,
3924
+ requestPath
3925
+ }) => {
3926
+ requestPath = requestPath.replace(/\/$/, "");
3927
+ entrypoint = entrypoint.replace(/\\/g, "/");
3928
+ if (entrypoint === requestPath && hasProp(files, entrypoint)) {
3929
+ return true;
3930
+ }
3931
+ const { dir, name } = (0, import_path5.parse)(entrypoint);
3932
+ if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
3933
+ return true;
3934
+ }
3935
+ return false;
3936
+ };
3937
+ function hasProp(obj, key) {
3938
+ return Object.hasOwnProperty.call(obj, key);
3939
+ }
3367
3940
  // Annotate the CommonJS export names for ESM import in node:
3368
3941
  0 && (module.exports = {
3369
3942
  build,
3943
+ defaultShouldServe,
3370
3944
  downloadFilesInWorkPath,
3371
3945
  installRequirement,
3372
3946
  installRequirementsFile,
3373
3947
  shouldServe,
3948
+ startDevServer,
3374
3949
  version
3375
3950
  });