@vercel/python 6.17.0 → 6.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +535 -138
  2. package/package.json +4 -4
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 fs7 = 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
+ fs7.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(fs7.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 fs7 = require("fs");
92
92
  function isexe(path, options, cb) {
93
- fs6.stat(path, function(er, stat) {
93
+ fs7.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(fs7.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 fs7 = 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 fs7 = 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 = fs7.openSync(command, "r");
412
+ fs7.readSync(fd, buffer, 0, size, 0);
413
+ fs7.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 debug7;
426
+ var debug9;
427
427
  if (typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG)) {
428
- debug7 = function() {
428
+ debug9 = 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
- debug7 = function() {
434
+ debug9 = function() {
435
435
  };
436
436
  }
437
437
  exports.SEMVER_SPEC_VERSION = "2.0.0";
@@ -540,7 +540,7 @@ var require_semver = __commonJS({
540
540
  var STAR = R++;
541
541
  src[STAR] = "(<|>)?=?\\s*\\*";
542
542
  for (i = 0; i < R; i++) {
543
- debug7(i, src[i]);
543
+ debug9(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]));
@@ -607,7 +607,7 @@ var require_semver = __commonJS({
607
607
  if (!(this instanceof SemVer)) {
608
608
  return new SemVer(version2, options);
609
609
  }
610
- debug7("SemVer", version2, options);
610
+ debug9("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
- debug7("SemVer.compare", this.version, this.options, other);
657
+ debug9("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
- debug7("prerelease compare", i2, a, b);
684
+ debug9("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) {
@@ -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
- debug7("comparator", comp, options);
938
+ debug9("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
- debug7("comp", this);
947
+ debug9("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
- debug7("Comparator.test", version2, this.options.loose);
970
+ debug9("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
- debug7("hyphen replace", range);
1053
+ debug9("hyphen replace", range);
1054
1054
  range = range.replace(safeRe[COMPARATORTRIM], comparatorTrimReplace);
1055
- debug7("comparator trim", range, safeRe[COMPARATORTRIM]);
1055
+ debug9("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
- debug7("comp", comp, options);
1095
+ debug9("comp", comp, options);
1096
1096
  comp = replaceCarets(comp, options);
1097
- debug7("caret", comp);
1097
+ debug9("caret", comp);
1098
1098
  comp = replaceTildes(comp, options);
1099
- debug7("tildes", comp);
1099
+ debug9("tildes", comp);
1100
1100
  comp = replaceXRanges(comp, options);
1101
- debug7("xrange", comp);
1101
+ debug9("xrange", comp);
1102
1102
  comp = replaceStars(comp, options);
1103
- debug7("stars", comp);
1103
+ debug9("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
- debug7("tilde", comp, _, M, m, p, pr);
1117
+ debug9("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
- debug7("replaceTilde pr", pr);
1126
+ debug9("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
- debug7("tilde return", ret);
1131
+ debug9("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
- debug7("caret", comp, options);
1141
+ debug9("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
- debug7("caret", comp, _, M, m, p, pr);
1144
+ debug9("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
- debug7("replaceCaret pr", pr);
1157
+ debug9("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
- debug7("no pr");
1168
+ debug9("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
- debug7("caret return", ret);
1179
+ debug9("caret return", ret);
1180
1180
  return ret;
1181
1181
  });
1182
1182
  }
1183
1183
  function replaceXRanges(comp, options) {
1184
- debug7("replaceXRanges", comp, options);
1184
+ debug9("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
- debug7("xRange", comp, ret, gtlt, M, m, p, pr);
1193
+ debug9("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
- debug7("xRange return", ret);
1236
+ debug9("xRange return", ret);
1237
1237
  return ret;
1238
1238
  });
1239
1239
  }
1240
1240
  function replaceStars(comp, options) {
1241
- debug7("replaceStars", comp, options);
1241
+ debug9("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
- debug7(set[i2].semver);
1289
+ debug9(set[i2].semver);
1290
1290
  if (set[i2].semver === ANY) {
1291
1291
  continue;
1292
1292
  }
@@ -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 fs7;
1899
1899
  try {
1900
- fs6 = require("fs");
1900
+ fs7 = 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 (!fs7)
1913
1913
  return false;
1914
- return (stream instanceof (fs6.ReadStream || noop) || stream instanceof (fs6.WriteStream || noop)) && isFn(stream.close);
1914
+ return (stream instanceof (fs7.ReadStream || noop) || stream instanceof (fs7.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: join8, delimiter: delimiter2, sep: sep2, posix } = require("path");
2654
+ var { join: join9, delimiter: delimiter2, sep: sep2, posix } = require("path");
2655
2655
  var isWindows = process.platform === "win32";
2656
2656
  var rSlash = new RegExp(`[${posix.sep}${sep2 === posix.sep ? "" : sep2}]`.replace(/(\\)/g, "\\$1"));
2657
2657
  var rRel = new RegExp(`^\\.${rSlash.source}`);
@@ -2680,7 +2680,7 @@ var require_lib = __commonJS({
2680
2680
  var getPathPart = (raw, cmd) => {
2681
2681
  const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw;
2682
2682
  const prefix = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : "";
2683
- return prefix + join8(pathPart, cmd);
2683
+ return prefix + join9(pathPart, cmd);
2684
2684
  };
2685
2685
  var which2 = async (cmd, opt = {}) => {
2686
2686
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
@@ -2867,15 +2867,15 @@ __export(src_exports, {
2867
2867
  version: () => version
2868
2868
  });
2869
2869
  module.exports = __toCommonJS(src_exports);
2870
- var import_fs6 = __toESM(require("fs"));
2870
+ var import_fs7 = __toESM(require("fs"));
2871
2871
  var import_util2 = require("util");
2872
- var import_path8 = require("path");
2872
+ var import_path9 = require("path");
2873
2873
 
2874
2874
  // src/package-versions.ts
2875
- var VERCEL_RUNTIME_VERSION = "0.5.2";
2875
+ var VERCEL_RUNTIME_VERSION = "0.5.3";
2876
2876
 
2877
2877
  // src/index.ts
2878
- var import_build_utils9 = require("@vercel/build-utils");
2878
+ var import_build_utils11 = require("@vercel/build-utils");
2879
2879
 
2880
2880
  // src/install.ts
2881
2881
  var import_execa3 = __toESM(require_execa());
@@ -3881,6 +3881,7 @@ var PythonDependencyExternalizer = class {
3881
3881
  this.noBuildCheckFailed = options.noBuildCheckFailed;
3882
3882
  this.pythonPath = options.pythonPath;
3883
3883
  this.hasCustomCommand = options.hasCustomCommand;
3884
+ this.alwaysBundlePackages = options.alwaysBundlePackages ?? [];
3884
3885
  }
3885
3886
  shouldEnableRuntimeInstall() {
3886
3887
  if (this.hasCustomCommand) {
@@ -4033,7 +4034,8 @@ ${error.fileContent}`
4033
4034
  const alwaysBundled = [
4034
4035
  ...classification.privatePackages,
4035
4036
  "vercel-runtime",
4036
- "vercel_runtime"
4037
+ "vercel_runtime",
4038
+ ...this.alwaysBundlePackages
4037
4039
  ];
4038
4040
  const alwaysBundledFiles = await mirrorPackagesIntoVendor({
4039
4041
  venvPath: this.venvPath,
@@ -4076,7 +4078,8 @@ ${error.fileContent}`
4076
4078
  }
4077
4079
  const bundledPackagesForConfig = [
4078
4080
  ...classification.privatePackages,
4079
- ...bundledPublic
4081
+ ...bundledPublic,
4082
+ ...this.alwaysBundlePackages
4080
4083
  ];
4081
4084
  const projectDirRel = (0, import_path5.relative)(this.workPath, this.uvProjectDir);
4082
4085
  const uvLockRel = (0, import_path5.relative)(this.workPath, this.uvLockPath);
@@ -4241,7 +4244,7 @@ async function calculatePerPackageSizes(venvPath) {
4241
4244
  }
4242
4245
 
4243
4246
  // src/index.ts
4244
- var import_build_utils10 = require("@vercel/build-utils");
4247
+ var import_build_utils12 = require("@vercel/build-utils");
4245
4248
 
4246
4249
  // src/start-dev-server.ts
4247
4250
  var import_child_process2 = require("child_process");
@@ -4877,9 +4880,399 @@ If you are using a virtual environment, activate it before running "vercel dev",
4877
4880
  }
4878
4881
  };
4879
4882
 
4883
+ // src/quirks/index.ts
4884
+ var import_build_utils10 = require("@vercel/build-utils");
4885
+ var import_python_analysis5 = require("@vercel/python-analysis");
4886
+
4887
+ // src/quirks/prisma.ts
4888
+ var import_fs6 = __toESM(require("fs"));
4889
+ var import_path8 = require("path");
4890
+ var import_execa4 = __toESM(require_execa());
4891
+ var import_build_utils9 = require("@vercel/build-utils");
4892
+ var import_python_analysis4 = require("@vercel/python-analysis");
4893
+ function execErrorMessage(err) {
4894
+ if (err != null && typeof err === "object" && "stderr" in err) {
4895
+ const stderr = String(err.stderr);
4896
+ if (stderr)
4897
+ return stderr;
4898
+ }
4899
+ return err instanceof Error ? err.message : String(err);
4900
+ }
4901
+ var DUMMY_SCHEMA_NAME = "_prisma_dummy.prisma";
4902
+ var LAMBDA_ROOT = "/var/task";
4903
+ var RUNTIME_OPENSSL_VERSION = "3.2";
4904
+ function getLambdaBinaryTarget() {
4905
+ return process.arch === "arm64" ? "linux-arm64-openssl-3.0.x" : "rhel-openssl-3.0.x";
4906
+ }
4907
+ function buildDummySchema(generatedDir) {
4908
+ const lambdaTarget = getLambdaBinaryTarget();
4909
+ return `datasource db {
4910
+ provider = "sqlite"
4911
+ url = "file:dev.db"
4912
+ }
4913
+
4914
+ generator client {
4915
+ provider = "prisma-client-py"
4916
+ binaryTargets = ["native", "${lambdaTarget}"]
4917
+ output = "${generatedDir}"
4918
+ }
4919
+
4920
+ model DummyModel {
4921
+ id Int @id
4922
+ }
4923
+ `;
4924
+ }
4925
+ async function findUserSchema(workPath) {
4926
+ const envPath = process.env.PRISMA_SCHEMA_PATH;
4927
+ if (envPath) {
4928
+ const resolved = (0, import_path8.isAbsolute)(envPath) ? envPath : (0, import_path8.join)(workPath, envPath);
4929
+ try {
4930
+ await import_fs6.default.promises.access(resolved);
4931
+ return resolved;
4932
+ } catch {
4933
+ (0, import_build_utils9.debug)(`PRISMA_SCHEMA_PATH=${envPath} not found at ${resolved}`);
4934
+ return null;
4935
+ }
4936
+ }
4937
+ const candidates = [
4938
+ (0, import_path8.join)(workPath, "schema.prisma"),
4939
+ (0, import_path8.join)(workPath, "prisma", "schema.prisma")
4940
+ ];
4941
+ for (const candidate of candidates) {
4942
+ try {
4943
+ await import_fs6.default.promises.access(candidate);
4944
+ return candidate;
4945
+ } catch {
4946
+ }
4947
+ }
4948
+ return null;
4949
+ }
4950
+ async function collectFiles(dir, base) {
4951
+ const result = [];
4952
+ let entries;
4953
+ try {
4954
+ entries = await import_fs6.default.promises.readdir(dir, { withFileTypes: true });
4955
+ } catch {
4956
+ return result;
4957
+ }
4958
+ for (const entry of entries) {
4959
+ if (entry.name === "__pycache__")
4960
+ continue;
4961
+ const full = (0, import_path8.join)(dir, entry.name);
4962
+ if (entry.isDirectory()) {
4963
+ result.push(...await collectFiles(full, base));
4964
+ } else {
4965
+ result.push((0, import_path8.relative)(base, full));
4966
+ }
4967
+ }
4968
+ return result;
4969
+ }
4970
+ async function cleanCacheArtifacts(cacheDir, extras = []) {
4971
+ const paths = [
4972
+ (0, import_path8.join)(cacheDir, "node_modules"),
4973
+ (0, import_path8.join)(cacheDir, "package.json"),
4974
+ (0, import_path8.join)(cacheDir, "package-lock.json"),
4975
+ ...extras
4976
+ ];
4977
+ for (const p of paths) {
4978
+ try {
4979
+ await import_fs6.default.promises.rm(p, { recursive: true, force: true });
4980
+ } catch (err) {
4981
+ console.warn(
4982
+ `could not clean up ${p}: ${err instanceof Error ? err.message : String(err)}`
4983
+ );
4984
+ }
4985
+ }
4986
+ }
4987
+ async function isClientGenerated(pythonPath, env) {
4988
+ try {
4989
+ await (0, import_execa4.default)(pythonPath, ["-c", "import prisma.client"], {
4990
+ env,
4991
+ stdio: "pipe"
4992
+ });
4993
+ return true;
4994
+ } catch {
4995
+ return false;
4996
+ }
4997
+ }
4998
+ var prismaQuirk = {
4999
+ dependency: "prisma",
5000
+ async run(ctx) {
5001
+ const { venvPath, pythonEnv, workPath } = ctx;
5002
+ const pythonPath = getVenvPythonBin(venvPath);
5003
+ const runtimeCacheDir = (0, import_path8.join)(
5004
+ LAMBDA_ROOT,
5005
+ resolveVendorDir(),
5006
+ "prisma",
5007
+ "__bincache__"
5008
+ );
5009
+ const sitePackagesDirs = await getVenvSitePackagesDirs(venvPath);
5010
+ let sitePackages;
5011
+ for (const dir of sitePackagesDirs) {
5012
+ try {
5013
+ await import_fs6.default.promises.access((0, import_path8.join)(dir, "prisma"));
5014
+ sitePackages = dir;
5015
+ break;
5016
+ } catch {
5017
+ }
5018
+ }
5019
+ if (!sitePackages) {
5020
+ console.warn(
5021
+ "prisma: could not find prisma in any site-packages directory"
5022
+ );
5023
+ return {};
5024
+ }
5025
+ const cacheDir = (0, import_path8.join)(sitePackages, "prisma", "__bincache__");
5026
+ await import_fs6.default.promises.mkdir(cacheDir, { recursive: true });
5027
+ const generateEnv = {
5028
+ ...pythonEnv,
5029
+ PRISMA_BINARY_CACHE_DIR: cacheDir
5030
+ };
5031
+ const generatedDir = (0, import_path8.join)(workPath, "_prisma_generated");
5032
+ const dummySchemaPath = (0, import_path8.join)(workPath, DUMMY_SCHEMA_NAME);
5033
+ await import_fs6.default.promises.writeFile(
5034
+ dummySchemaPath,
5035
+ buildDummySchema(generatedDir)
5036
+ );
5037
+ (0, import_build_utils9.debug)(`Running prisma generate (dummy) with cache dir: ${cacheDir}`);
5038
+ try {
5039
+ const dummyResult = await (0, import_execa4.default)(
5040
+ pythonPath,
5041
+ ["-m", "prisma", "generate", `--schema=${dummySchemaPath}`],
5042
+ {
5043
+ cwd: workPath,
5044
+ env: generateEnv,
5045
+ stdio: "pipe"
5046
+ }
5047
+ );
5048
+ if (dummyResult.stdout)
5049
+ (0, import_build_utils9.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
5050
+ if (dummyResult.stderr)
5051
+ (0, import_build_utils9.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
5052
+ } catch (err) {
5053
+ throw new import_build_utils9.NowBuildError({
5054
+ code: "PRISMA_GENERATE_FAILED",
5055
+ message: `Prisma engine download failed during \`prisma generate\`. Check that your prisma version is compatible with this Python version.
5056
+ ` + execErrorMessage(err)
5057
+ });
5058
+ }
5059
+ const srcBinaryPrefix = `query-engine-${getLambdaBinaryTarget()}`;
5060
+ const runtimeName = `prisma-query-engine-rhel-openssl-${RUNTIME_OPENSSL_VERSION}.x`;
5061
+ const nodeModulesDir = (0, import_path8.join)(cacheDir, "node_modules", "prisma");
5062
+ let engineCopied = false;
5063
+ try {
5064
+ const entries = await import_fs6.default.promises.readdir(nodeModulesDir);
5065
+ for (const entry of entries) {
5066
+ if (!entry.startsWith(srcBinaryPrefix))
5067
+ continue;
5068
+ const srcPath = (0, import_path8.join)(nodeModulesDir, entry);
5069
+ const destPath = (0, import_path8.join)(cacheDir, runtimeName);
5070
+ try {
5071
+ await import_fs6.default.promises.access(destPath);
5072
+ (0, import_build_utils9.debug)(`Engine binary: ${runtimeName} already exists, skipping`);
5073
+ } catch {
5074
+ (0, import_build_utils9.debug)(`Engine binary: copying ${entry} -> ${runtimeName}`);
5075
+ await import_fs6.default.promises.copyFile(srcPath, destPath);
5076
+ }
5077
+ engineCopied = true;
5078
+ }
5079
+ } catch (err) {
5080
+ throw new import_build_utils9.NowBuildError({
5081
+ code: "PRISMA_ENGINE_NOT_FOUND",
5082
+ message: `could not read Prisma engine directory "${nodeModulesDir}". This may indicate an incompatible prisma version.
5083
+ ` + (err instanceof Error ? err.message : String(err))
5084
+ });
5085
+ }
5086
+ if (!engineCopied) {
5087
+ throw new import_build_utils9.NowBuildError({
5088
+ code: "PRISMA_ENGINE_NOT_FOUND",
5089
+ message: `could not find engine binary matching "${srcBinaryPrefix}*" in "${nodeModulesDir}". This may indicate an incompatible prisma version or an unsupported platform (${process.arch}).`
5090
+ });
5091
+ }
5092
+ const shimPath = (0, import_path8.join)(cacheDir, "openssl");
5093
+ await import_fs6.default.promises.writeFile(
5094
+ shimPath,
5095
+ `#!/bin/sh
5096
+ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIME_OPENSSL_VERSION}.0)"
5097
+ `
5098
+ );
5099
+ await import_fs6.default.promises.chmod(shimPath, 493);
5100
+ for (const p of [generatedDir, dummySchemaPath]) {
5101
+ await import_fs6.default.promises.rm(p, { recursive: true, force: true });
5102
+ }
5103
+ await cleanCacheArtifacts(cacheDir);
5104
+ const generateMode = (process.env.VERCEL_PRISMA_GENERATE_CLIENT ?? "auto").toLowerCase();
5105
+ const userSchema = generateMode !== "never" ? await findUserSchema(workPath) : null;
5106
+ if (userSchema) {
5107
+ let shouldGenerate = true;
5108
+ if (generateMode === "auto") {
5109
+ const clientAlreadyGenerated = await isClientGenerated(
5110
+ pythonPath,
5111
+ pythonEnv
5112
+ );
5113
+ if (clientAlreadyGenerated) {
5114
+ (0, import_build_utils9.debug)(
5115
+ "Prisma quirk: client already generated, skipping user schema generate"
5116
+ );
5117
+ shouldGenerate = false;
5118
+ }
5119
+ }
5120
+ if (shouldGenerate) {
5121
+ (0, import_build_utils9.debug)(`Running prisma generate with user schema: ${userSchema}`);
5122
+ try {
5123
+ const userResult = await (0, import_execa4.default)(
5124
+ pythonPath,
5125
+ ["-m", "prisma", "generate", `--schema=${userSchema}`],
5126
+ {
5127
+ cwd: workPath,
5128
+ env: generateEnv,
5129
+ stdio: "pipe"
5130
+ }
5131
+ );
5132
+ if (userResult.stdout)
5133
+ (0, import_build_utils9.debug)(`prisma generate stdout: ${userResult.stdout}`);
5134
+ if (userResult.stderr)
5135
+ (0, import_build_utils9.debug)(`prisma generate stderr: ${userResult.stderr}`);
5136
+ } catch (err) {
5137
+ throw new import_build_utils9.NowBuildError({
5138
+ code: "PRISMA_GENERATE_FAILED",
5139
+ message: `\`prisma generate\` failed for schema "${userSchema}".
5140
+ ` + execErrorMessage(err)
5141
+ });
5142
+ }
5143
+ await cleanCacheArtifacts(cacheDir);
5144
+ }
5145
+ }
5146
+ try {
5147
+ const allFiles = await collectFiles(
5148
+ (0, import_path8.join)(sitePackages, "prisma"),
5149
+ sitePackages
5150
+ );
5151
+ const count = await (0, import_python_analysis4.extendDistRecord)(sitePackages, "prisma", allFiles);
5152
+ if (count > 0) {
5153
+ (0, import_build_utils9.debug)(`Appended ${count} entries to prisma RECORD`);
5154
+ }
5155
+ } catch (err) {
5156
+ console.warn(
5157
+ `could not patch prisma RECORD: ${err instanceof Error ? err.message : String(err)}`
5158
+ );
5159
+ }
5160
+ return {
5161
+ env: {
5162
+ PRISMA_BINARY_CACHE_DIR: runtimeCacheDir,
5163
+ VERCEL_RUNTIME_ENV_PATH_PREPEND: runtimeCacheDir
5164
+ },
5165
+ buildEnv: { PRISMA_BINARY_CACHE_DIR: cacheDir },
5166
+ alwaysBundlePackages: ["prisma"]
5167
+ };
5168
+ }
5169
+ };
5170
+
5171
+ // src/quirks/index.ts
5172
+ var quirks = [prismaQuirk];
5173
+ function toposortQuirks(activated) {
5174
+ const nameToQuirk = /* @__PURE__ */ new Map();
5175
+ for (const q of activated) {
5176
+ nameToQuirk.set((0, import_python_analysis5.normalizePackageName)(q.dependency), q);
5177
+ }
5178
+ const adj = /* @__PURE__ */ new Map();
5179
+ const inDegree = /* @__PURE__ */ new Map();
5180
+ for (const q of activated) {
5181
+ adj.set(q, /* @__PURE__ */ new Set());
5182
+ inDegree.set(q, 0);
5183
+ }
5184
+ for (const q of activated) {
5185
+ if (q.runsBefore) {
5186
+ for (const dep of q.runsBefore) {
5187
+ const target = nameToQuirk.get((0, import_python_analysis5.normalizePackageName)(dep));
5188
+ if (target) {
5189
+ adj.get(q).add(target);
5190
+ inDegree.set(target, inDegree.get(target) + 1);
5191
+ }
5192
+ }
5193
+ }
5194
+ if (q.runsAfter) {
5195
+ for (const dep of q.runsAfter) {
5196
+ const source = nameToQuirk.get((0, import_python_analysis5.normalizePackageName)(dep));
5197
+ if (source) {
5198
+ adj.get(source).add(q);
5199
+ inDegree.set(q, inDegree.get(q) + 1);
5200
+ }
5201
+ }
5202
+ }
5203
+ }
5204
+ const queue = [];
5205
+ for (const q of activated) {
5206
+ if (inDegree.get(q) === 0) {
5207
+ queue.push(q);
5208
+ }
5209
+ }
5210
+ const sorted = [];
5211
+ while (queue.length > 0) {
5212
+ const q = queue.shift();
5213
+ sorted.push(q);
5214
+ for (const neighbor of adj.get(q)) {
5215
+ const deg = inDegree.get(neighbor) - 1;
5216
+ inDegree.set(neighbor, deg);
5217
+ if (deg === 0) {
5218
+ queue.push(neighbor);
5219
+ }
5220
+ }
5221
+ }
5222
+ if (sorted.length !== activated.length) {
5223
+ const unsorted = activated.filter((q) => !sorted.includes(q)).map((q) => q.dependency);
5224
+ throw new Error(
5225
+ `Circular dependency detected among quirks: ${unsorted.join(", ")}`
5226
+ );
5227
+ }
5228
+ return sorted;
5229
+ }
5230
+ async function runQuirks(ctx) {
5231
+ const mergedEnv = {};
5232
+ const mergedBuildEnv = {};
5233
+ const mergedAlwaysBundle = [];
5234
+ const installedNames = /* @__PURE__ */ new Set();
5235
+ const sitePackageDirs = await getVenvSitePackagesDirs(ctx.venvPath);
5236
+ for (const dir of sitePackageDirs) {
5237
+ const distributions = await (0, import_python_analysis5.scanDistributions)(dir);
5238
+ for (const name of distributions.keys()) {
5239
+ installedNames.add((0, import_python_analysis5.normalizePackageName)(name));
5240
+ }
5241
+ }
5242
+ const activated = quirks.filter((quirk) => {
5243
+ const installed = installedNames.has(
5244
+ (0, import_python_analysis5.normalizePackageName)(quirk.dependency)
5245
+ );
5246
+ if (!installed) {
5247
+ (0, import_build_utils10.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
5248
+ }
5249
+ return installed;
5250
+ });
5251
+ const sorted = toposortQuirks(activated);
5252
+ for (const quirk of sorted) {
5253
+ (0, import_build_utils10.debug)(`Quirk "${quirk.dependency}": detected, running fix-up`);
5254
+ const result = await quirk.run(ctx);
5255
+ if (result.env) {
5256
+ Object.assign(mergedEnv, result.env);
5257
+ }
5258
+ if (result.buildEnv) {
5259
+ Object.assign(mergedBuildEnv, result.buildEnv);
5260
+ Object.assign(process.env, result.buildEnv);
5261
+ }
5262
+ if (result.alwaysBundlePackages) {
5263
+ mergedAlwaysBundle.push(...result.alwaysBundlePackages);
5264
+ }
5265
+ }
5266
+ return {
5267
+ env: mergedEnv,
5268
+ buildEnv: mergedBuildEnv,
5269
+ alwaysBundlePackages: mergedAlwaysBundle
5270
+ };
5271
+ }
5272
+
4880
5273
  // src/index.ts
4881
- var readFile2 = (0, import_util2.promisify)(import_fs6.default.readFile);
4882
- var writeFile = (0, import_util2.promisify)(import_fs6.default.writeFile);
5274
+ var readFile2 = (0, import_util2.promisify)(import_fs7.default.readFile);
5275
+ var writeFile = (0, import_util2.promisify)(import_fs7.default.writeFile);
4883
5276
  var version = 3;
4884
5277
  async function downloadFilesInWorkPath({
4885
5278
  entrypoint,
@@ -4887,13 +5280,13 @@ async function downloadFilesInWorkPath({
4887
5280
  files,
4888
5281
  meta = {}
4889
5282
  }) {
4890
- (0, import_build_utils9.debug)("Downloading user files...");
4891
- let downloadedFiles = await (0, import_build_utils9.download)(files, workPath, meta);
5283
+ (0, import_build_utils11.debug)("Downloading user files...");
5284
+ let downloadedFiles = await (0, import_build_utils11.download)(files, workPath, meta);
4892
5285
  if (meta.isDev) {
4893
- const { devCacheDir = (0, import_path8.join)(workPath, ".now", "cache") } = meta;
4894
- const destCache = (0, import_path8.join)(devCacheDir, (0, import_path8.basename)(entrypoint, ".py"));
4895
- await (0, import_build_utils9.download)(downloadedFiles, destCache);
4896
- downloadedFiles = await (0, import_build_utils9.glob)("**", destCache);
5286
+ const { devCacheDir = (0, import_path9.join)(workPath, ".now", "cache") } = meta;
5287
+ const destCache = (0, import_path9.join)(devCacheDir, (0, import_path9.basename)(entrypoint, ".py"));
5288
+ await (0, import_build_utils11.download)(downloadedFiles, destCache);
5289
+ downloadedFiles = await (0, import_build_utils11.glob)("**", destCache);
4897
5290
  workPath = destCache;
4898
5291
  }
4899
5292
  return workPath;
@@ -4910,7 +5303,7 @@ var build = async ({
4910
5303
  let spawnEnv;
4911
5304
  let projectInstallCommand;
4912
5305
  let hasCustomCommand = false;
4913
- (0, import_build_utils9.debug)(`workPath: ${workPath}`);
5306
+ (0, import_build_utils11.debug)(`workPath: ${workPath}`);
4914
5307
  workPath = await downloadFilesInWorkPath({
4915
5308
  workPath,
4916
5309
  files: originalFiles,
@@ -4919,72 +5312,28 @@ var build = async ({
4919
5312
  });
4920
5313
  try {
4921
5314
  if (meta.isDev) {
4922
- const setupCfg = (0, import_path8.join)(workPath, "setup.cfg");
5315
+ const setupCfg = (0, import_path9.join)(workPath, "setup.cfg");
4923
5316
  await writeFile(setupCfg, "[install]\nprefix=\n");
4924
5317
  }
4925
5318
  } catch (err) {
4926
5319
  console.log('Failed to create "setup.cfg" file');
4927
5320
  throw err;
4928
5321
  }
4929
- if ((0, import_build_utils9.isPythonFramework)(framework)) {
4930
- const {
4931
- cliType,
4932
- lockfileVersion,
4933
- packageJsonPackageManager,
4934
- turboSupportsCorepackHome
4935
- } = await (0, import_build_utils9.scanParentDirs)(workPath, true);
4936
- spawnEnv = (0, import_build_utils9.getEnvForPackageManager)({
4937
- cliType,
4938
- lockfileVersion,
4939
- packageJsonPackageManager,
4940
- env: process.env,
4941
- turboSupportsCorepackHome,
4942
- projectCreatedAt: config?.projectSettings?.createdAt
4943
- });
4944
- const installCommand = config?.projectSettings?.installCommand;
4945
- if (typeof installCommand === "string") {
4946
- const trimmed = installCommand.trim();
4947
- if (trimmed) {
4948
- projectInstallCommand = trimmed;
4949
- } else {
4950
- console.log('Skipping "install" command...');
4951
- }
4952
- }
4953
- const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
4954
- config?.buildCommand;
4955
- if (projectBuildCommand) {
4956
- console.log(`Running "${projectBuildCommand}"`);
4957
- await (0, import_build_utils9.execCommand)(projectBuildCommand, {
4958
- env: spawnEnv,
4959
- cwd: workPath
4960
- });
4961
- hasCustomCommand = true;
4962
- } else {
4963
- const ranBuildScript = await runPyprojectScript(
4964
- workPath,
4965
- ["vercel-build", "now-build", "build"],
4966
- spawnEnv
4967
- );
4968
- if (ranBuildScript) {
4969
- hasCustomCommand = true;
4970
- }
4971
- }
4972
- }
4973
- let fsFiles = await (0, import_build_utils9.glob)("**", workPath);
4974
- if ((0, import_build_utils9.isPythonFramework)(framework) && (!fsFiles[entrypoint] || !entrypoint.endsWith(".py"))) {
5322
+ let fsFiles = await (0, import_build_utils11.glob)("**", workPath);
5323
+ if ((0, import_build_utils11.isPythonFramework)(framework) && (!fsFiles[entrypoint] || !entrypoint.endsWith(".py"))) {
4975
5324
  const detected = await detectPythonEntrypoint(
4976
5325
  config.framework,
4977
5326
  workPath,
4978
5327
  entrypoint
4979
5328
  );
4980
5329
  if (detected) {
4981
- (0, import_build_utils9.debug)(
5330
+ (0, import_build_utils11.debug)(
4982
5331
  `Resolved Python entrypoint to "${detected}" (configured "${entrypoint}" not found).`
4983
5332
  );
4984
5333
  entrypoint = detected;
4985
5334
  } else {
4986
5335
  const searchedList = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
4987
- throw new import_build_utils9.NowBuildError({
5336
+ throw new import_build_utils11.NowBuildError({
4988
5337
  code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
4989
5338
  message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
4990
5339
  link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
@@ -4992,7 +5341,7 @@ var build = async ({
4992
5341
  });
4993
5342
  }
4994
5343
  }
4995
- const entryDirectory = (0, import_path8.dirname)(entrypoint);
5344
+ const entryDirectory = (0, import_path9.dirname)(entrypoint);
4996
5345
  const pyprojectDir = findDir({
4997
5346
  file: "pyproject.toml",
4998
5347
  entryDirectory,
@@ -5015,37 +5364,37 @@ var build = async ({
5015
5364
  if (pythonVersionFileDir) {
5016
5365
  try {
5017
5366
  const content = await readFile2(
5018
- (0, import_path8.join)(pythonVersionFileDir, ".python-version"),
5367
+ (0, import_path9.join)(pythonVersionFileDir, ".python-version"),
5019
5368
  "utf8"
5020
5369
  );
5021
5370
  const version2 = parsePythonVersionFile(content);
5022
5371
  if (version2) {
5023
5372
  declaredPythonVersion = { version: version2, source: ".python-version" };
5024
- (0, import_build_utils9.debug)(`Found Python version ${version2} in .python-version`);
5373
+ (0, import_build_utils11.debug)(`Found Python version ${version2} in .python-version`);
5025
5374
  }
5026
5375
  } catch (err) {
5027
- (0, import_build_utils9.debug)("Failed to read .python-version file", err);
5376
+ (0, import_build_utils11.debug)("Failed to read .python-version file", err);
5028
5377
  }
5029
5378
  }
5030
5379
  if (!declaredPythonVersion && pyprojectDir) {
5031
5380
  let requiresPython;
5032
5381
  try {
5033
- const pyproject = await (0, import_build_utils10.readConfigFile)((0, import_path8.join)(pyprojectDir, "pyproject.toml"));
5382
+ const pyproject = await (0, import_build_utils12.readConfigFile)((0, import_path9.join)(pyprojectDir, "pyproject.toml"));
5034
5383
  requiresPython = pyproject?.project?.["requires-python"];
5035
5384
  } catch (err) {
5036
- (0, import_build_utils9.debug)("Failed to parse pyproject.toml", err);
5385
+ (0, import_build_utils11.debug)("Failed to parse pyproject.toml", err);
5037
5386
  }
5038
5387
  if (typeof requiresPython === "string" && requiresPython.trim()) {
5039
5388
  declaredPythonVersion = {
5040
5389
  version: requiresPython.trim(),
5041
5390
  source: "pyproject.toml"
5042
5391
  };
5043
- (0, import_build_utils9.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
5392
+ (0, import_build_utils11.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
5044
5393
  }
5045
5394
  }
5046
5395
  if (!declaredPythonVersion && pipfileLockDir) {
5047
5396
  let lock = {};
5048
- const pipfileLockPath = (0, import_path8.join)(pipfileLockDir, "Pipfile.lock");
5397
+ const pipfileLockPath = (0, import_path9.join)(pipfileLockDir, "Pipfile.lock");
5049
5398
  try {
5050
5399
  const pipfileLockContent = await readFile2(pipfileLockPath, "utf8");
5051
5400
  try {
@@ -5058,7 +5407,7 @@ ${pipfileLockContent}`
5058
5407
  throw err;
5059
5408
  }
5060
5409
  } catch (err) {
5061
- throw new import_build_utils9.NowBuildError({
5410
+ throw new import_build_utils11.NowBuildError({
5062
5411
  code: "INVALID_PIPFILE_LOCK",
5063
5412
  message: "Unable to parse Pipfile.lock"
5064
5413
  });
@@ -5066,7 +5415,7 @@ ${pipfileLockContent}`
5066
5415
  const pyFromLock = lock?._meta?.requires?.python_version;
5067
5416
  if (pyFromLock) {
5068
5417
  declaredPythonVersion = { version: pyFromLock, source: "Pipfile.lock" };
5069
- (0, import_build_utils9.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
5418
+ (0, import_build_utils11.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
5070
5419
  }
5071
5420
  }
5072
5421
  const pythonVersion = getSupportedPythonVersion({
@@ -5076,26 +5425,51 @@ ${pipfileLockContent}`
5076
5425
  const selectedVersionTuple = parseVersionTuple(pythonVersion.version);
5077
5426
  const defaultVersionTuple = parseVersionTuple(DEFAULT_PYTHON_VERSION);
5078
5427
  if (!pythonVersionFileDir && pyprojectDir && declaredPythonVersion?.source === "pyproject.toml" && selectedVersionTuple && defaultVersionTuple && compareTuples(selectedVersionTuple, defaultVersionTuple) <= 0) {
5079
- const pythonVersionFilePath = (0, import_path8.join)(pyprojectDir, ".python-version");
5428
+ const pythonVersionFilePath = (0, import_path9.join)(pyprojectDir, ".python-version");
5080
5429
  await writeFile(pythonVersionFilePath, `${pythonVersion.version}
5081
5430
  `);
5082
5431
  console.log(
5083
5432
  `Writing .python-version file with version ${pythonVersion.version}`
5084
5433
  );
5085
5434
  }
5086
- fsFiles = await (0, import_build_utils9.glob)("**", workPath);
5087
- const venvPath = (0, import_path8.join)(workPath, ".vercel", "python", ".venv");
5435
+ fsFiles = await (0, import_build_utils11.glob)("**", workPath);
5436
+ const venvPath = (0, import_path9.join)(workPath, ".vercel", "python", ".venv");
5088
5437
  await ensureVenv({
5089
5438
  pythonPath: pythonVersion.pythonPath,
5090
5439
  venvPath
5091
5440
  });
5441
+ if ((0, import_build_utils11.isPythonFramework)(framework)) {
5442
+ const {
5443
+ cliType,
5444
+ lockfileVersion,
5445
+ packageJsonPackageManager,
5446
+ turboSupportsCorepackHome
5447
+ } = await (0, import_build_utils11.scanParentDirs)(workPath, true);
5448
+ spawnEnv = (0, import_build_utils11.getEnvForPackageManager)({
5449
+ cliType,
5450
+ lockfileVersion,
5451
+ packageJsonPackageManager,
5452
+ env: process.env,
5453
+ turboSupportsCorepackHome,
5454
+ projectCreatedAt: config?.projectSettings?.createdAt
5455
+ });
5456
+ const installCommand = config?.projectSettings?.installCommand;
5457
+ if (typeof installCommand === "string") {
5458
+ const trimmed = installCommand.trim();
5459
+ if (trimmed) {
5460
+ projectInstallCommand = trimmed;
5461
+ } else {
5462
+ console.log('Skipping "install" command...');
5463
+ }
5464
+ }
5465
+ }
5092
5466
  const baseEnv = spawnEnv || process.env;
5093
5467
  const pythonEnv = createVenvEnv(venvPath, baseEnv);
5094
5468
  pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
5095
5469
  let assumeDepsInstalled = false;
5096
5470
  if (projectInstallCommand) {
5097
5471
  console.log(`Running "install" command: \`${projectInstallCommand}\`...`);
5098
- await (0, import_build_utils9.execCommand)(projectInstallCommand, {
5472
+ await (0, import_build_utils11.execCommand)(projectInstallCommand, {
5099
5473
  env: pythonEnv,
5100
5474
  cwd: workPath
5101
5475
  });
@@ -5156,7 +5530,7 @@ ${pipfileLockContent}`
5156
5530
  });
5157
5531
  } catch (err) {
5158
5532
  noBuildCheckFailed = true;
5159
- (0, import_build_utils9.debug)(
5533
+ (0, import_build_utils11.debug)(
5160
5534
  `--no-build check failed: ${err instanceof Error ? err.message : String(err)}`
5161
5535
  );
5162
5536
  }
@@ -5168,19 +5542,40 @@ ${pipfileLockContent}`
5168
5542
  locked: !lockFileProvidedByUser
5169
5543
  });
5170
5544
  }
5545
+ if ((0, import_build_utils11.isPythonFramework)(framework)) {
5546
+ const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
5547
+ config?.buildCommand;
5548
+ if (projectBuildCommand) {
5549
+ console.log(`Running "${projectBuildCommand}"`);
5550
+ await (0, import_build_utils11.execCommand)(projectBuildCommand, {
5551
+ env: pythonEnv,
5552
+ cwd: workPath
5553
+ });
5554
+ } else {
5555
+ await runPyprojectScript(
5556
+ workPath,
5557
+ ["vercel-build", "now-build", "build"],
5558
+ pythonEnv
5559
+ );
5560
+ }
5561
+ }
5171
5562
  const runtimeDep = baseEnv.VERCEL_RUNTIME_PYTHON || `vercel-runtime==${VERCEL_RUNTIME_VERSION}`;
5172
- (0, import_build_utils9.debug)(`Installing ${runtimeDep}`);
5563
+ (0, import_build_utils11.debug)(`Installing ${runtimeDep}`);
5173
5564
  await uv.pip({
5174
5565
  venvPath,
5175
- projectDir: (0, import_path8.join)(workPath, entryDirectory),
5566
+ projectDir: (0, import_path9.join)(workPath, entryDirectory),
5176
5567
  args: ["install", runtimeDep]
5177
5568
  });
5178
- (0, import_build_utils9.debug)("Entrypoint is", entrypoint);
5569
+ const quirksResult = await runQuirks({ venvPath, pythonEnv, workPath });
5570
+ if (quirksResult.buildEnv) {
5571
+ Object.assign(pythonEnv, quirksResult.buildEnv);
5572
+ }
5573
+ (0, import_build_utils11.debug)("Entrypoint is", entrypoint);
5179
5574
  const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
5180
5575
  const vendorDir = resolveVendorDir();
5181
5576
  const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
5182
5577
  const entrypointWithSuffix = `${entrypoint}${suffix}`;
5183
- (0, import_build_utils9.debug)("Entrypoint with suffix is", entrypointWithSuffix);
5578
+ (0, import_build_utils11.debug)("Entrypoint with suffix is", entrypointWithSuffix);
5184
5579
  const runtimeTrampoline = `
5185
5580
  import importlib
5186
5581
  import os
@@ -5239,11 +5634,12 @@ from vercel_runtime.vc_init import vc_handler
5239
5634
  ];
5240
5635
  const lambdaEnv = {};
5241
5636
  lambdaEnv.PYTHONPATH = vendorDir;
5637
+ Object.assign(lambdaEnv, quirksResult.env);
5242
5638
  const globOptions = {
5243
5639
  cwd: workPath,
5244
5640
  ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
5245
5641
  };
5246
- const files = await (0, import_build_utils9.glob)("**", globOptions);
5642
+ const files = await (0, import_build_utils11.glob)("**", globOptions);
5247
5643
  const depExternalizer = new PythonDependencyExternalizer({
5248
5644
  venvPath,
5249
5645
  vendorDir,
@@ -5253,7 +5649,8 @@ from vercel_runtime.vc_init import vc_handler
5253
5649
  projectName,
5254
5650
  noBuildCheckFailed,
5255
5651
  pythonPath: pythonVersion.pythonPath,
5256
- hasCustomCommand
5652
+ hasCustomCommand,
5653
+ alwaysBundlePackages: quirksResult.alwaysBundlePackages
5257
5654
  });
5258
5655
  const { runtimeInstallEnabled, allVendorFiles } = await depExternalizer.analyze(files);
5259
5656
  if (runtimeInstallEnabled) {
@@ -5264,12 +5661,12 @@ from vercel_runtime.vc_init import vc_handler
5264
5661
  }
5265
5662
  }
5266
5663
  const handlerPyFilename = "vc__handler__python";
5267
- files[`${handlerPyFilename}.py`] = new import_build_utils9.FileBlob({ data: runtimeTrampoline });
5664
+ files[`${handlerPyFilename}.py`] = new import_build_utils11.FileBlob({ data: runtimeTrampoline });
5268
5665
  if (config.framework === "fasthtml") {
5269
5666
  const { SESSKEY = "" } = process.env;
5270
- files[".sesskey"] = new import_build_utils9.FileBlob({ data: `"${SESSKEY}"` });
5667
+ files[".sesskey"] = new import_build_utils11.FileBlob({ data: `"${SESSKEY}"` });
5271
5668
  }
5272
- const output = new import_build_utils9.Lambda({
5669
+ const output = new import_build_utils11.Lambda({
5273
5670
  files,
5274
5671
  handler: `${handlerPyFilename}.vc_handler`,
5275
5672
  runtime: pythonVersion.runtime,
@@ -5280,7 +5677,7 @@ from vercel_runtime.vc_init import vc_handler
5280
5677
  };
5281
5678
  var shouldServe = (opts) => {
5282
5679
  const framework = opts.config.framework;
5283
- if ((0, import_build_utils9.isPythonFramework)(framework)) {
5680
+ if ((0, import_build_utils11.isPythonFramework)(framework)) {
5284
5681
  const requestPath = opts.requestPath.replace(/\/$/, "");
5285
5682
  if (requestPath.startsWith("api") && opts.hasMatched) {
5286
5683
  return false;
@@ -5299,7 +5696,7 @@ var defaultShouldServe = ({
5299
5696
  if (entrypoint === requestPath && hasProp(files, entrypoint)) {
5300
5697
  return true;
5301
5698
  }
5302
- const { dir, name } = (0, import_path8.parse)(entrypoint);
5699
+ const { dir, name } = (0, import_path9.parse)(entrypoint);
5303
5700
  if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
5304
5701
  return true;
5305
5702
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "6.17.0",
3
+ "version": "6.18.0",
4
4
  "main": "./dist/index.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -15,7 +15,7 @@
15
15
  "directory": "packages/python"
16
16
  },
17
17
  "dependencies": {
18
- "@vercel/python-analysis": "0.8.0"
18
+ "@vercel/python-analysis": "0.8.1"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@renovatebot/pep440": "4.2.1",
@@ -35,9 +35,9 @@
35
35
  "which": "3.0.0",
36
36
  "get-port": "5.1.1",
37
37
  "is-port-reachable": "3.1.0",
38
- "@vercel/build-utils": "13.6.0",
38
+ "@vercel/python-runtime": "0.5.3",
39
39
  "@vercel/error-utils": "2.0.3",
40
- "@vercel/python-runtime": "0.5.2"
40
+ "@vercel/build-utils": "13.6.1"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "node ../../utils/build-builder.mjs",