@vercel/python 6.22.0 → 6.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -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 fs9 = require("fs");
51
+ var fs10 = 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
- fs9.stat(path, function(er, stat) {
76
+ fs10.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(fs9.statSync(path), path, options);
81
+ return checkStat(fs10.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 fs9 = require("fs");
91
+ var fs10 = require("fs");
92
92
  function isexe(path, options, cb) {
93
- fs9.stat(path, function(er, stat) {
93
+ fs10.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(fs9.statSync(path), options);
98
+ return checkStat(fs10.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 fs9 = require("fs");
122
+ var fs10 = require("fs");
123
123
  var core;
124
124
  if (process.platform === "win32" || global.TESTING_WINDOWS) {
125
125
  core = require_windows();
@@ -137,12 +137,12 @@ var require_isexe = __commonJS({
137
137
  if (typeof Promise !== "function") {
138
138
  throw new TypeError("callback not provided");
139
139
  }
140
- return new Promise(function(resolve2, reject) {
140
+ return new Promise(function(resolve3, reject) {
141
141
  isexe(path, options || {}, function(er, is) {
142
142
  if (er) {
143
143
  reject(er);
144
144
  } else {
145
- resolve2(is);
145
+ resolve3(is);
146
146
  }
147
147
  });
148
148
  });
@@ -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 fs9 = require("fs");
398
+ var fs10 = 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 = fs9.openSync(command, "r");
412
- fs9.readSync(fd, buffer, 0, size, 0);
413
- fs9.closeSync(fd);
411
+ fd = fs10.openSync(command, "r");
412
+ fs10.readSync(fd, buffer, 0, size, 0);
413
+ fs10.closeSync(fd);
414
414
  } catch (e) {
415
415
  }
416
416
  return shebangCommand(buffer.toString());
@@ -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 fs9;
1898
+ var fs10;
1899
1899
  try {
1900
- fs9 = require("fs");
1900
+ fs10 = 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 (!fs9)
1912
+ if (!fs10)
1913
1913
  return false;
1914
- return (stream instanceof (fs9.ReadStream || noop) || stream instanceof (fs9.WriteStream || noop)) && isFn(stream.close);
1914
+ return (stream instanceof (fs10.ReadStream || noop) || stream instanceof (fs10.WriteStream || noop)) && isFn(stream.close);
1915
1915
  };
1916
1916
  var isRequest = function(stream) {
1917
1917
  return stream.setHeader && isFn(stream.abort);
@@ -2042,7 +2042,7 @@ var require_get_stream = __commonJS({
2042
2042
  options = Object.assign({ maxBuffer: Infinity }, options);
2043
2043
  const { maxBuffer } = options;
2044
2044
  let stream;
2045
- return new Promise((resolve2, reject) => {
2045
+ return new Promise((resolve3, reject) => {
2046
2046
  const rejectPromise = (error) => {
2047
2047
  if (error) {
2048
2048
  error.bufferedData = stream.getBufferedValue();
@@ -2054,7 +2054,7 @@ var require_get_stream = __commonJS({
2054
2054
  rejectPromise(error);
2055
2055
  return;
2056
2056
  }
2057
- resolve2();
2057
+ resolve3();
2058
2058
  });
2059
2059
  stream.on("data", () => {
2060
2060
  if (stream.getBufferedLength() > maxBuffer) {
@@ -2078,11 +2078,11 @@ var require_p_finally = __commonJS({
2078
2078
  onFinally = onFinally || (() => {
2079
2079
  });
2080
2080
  return promise.then(
2081
- (val) => new Promise((resolve2) => {
2082
- resolve2(onFinally());
2081
+ (val) => new Promise((resolve3) => {
2082
+ resolve3(onFinally());
2083
2083
  }).then(() => val),
2084
- (err) => new Promise((resolve2) => {
2085
- resolve2(onFinally());
2084
+ (err) => new Promise((resolve3) => {
2085
+ resolve3(onFinally());
2086
2086
  }).then(() => {
2087
2087
  throw err;
2088
2088
  })
@@ -2461,8 +2461,8 @@ var require_execa = __commonJS({
2461
2461
  }
2462
2462
  let ret;
2463
2463
  if (!buffer) {
2464
- ret = new Promise((resolve2, reject) => {
2465
- process2[stream].once("end", resolve2).once("error", reject);
2464
+ ret = new Promise((resolve3, reject) => {
2465
+ process2[stream].once("end", resolve3).once("error", reject);
2466
2466
  });
2467
2467
  } else if (encoding) {
2468
2468
  ret = _getStream(process2[stream], {
@@ -2551,19 +2551,19 @@ ${stderr}${stdout}`;
2551
2551
  spawned.kill(parsed.opts.killSignal);
2552
2552
  }, parsed.opts.timeout);
2553
2553
  }
2554
- const processDone = new Promise((resolve2) => {
2554
+ const processDone = new Promise((resolve3) => {
2555
2555
  spawned.on("exit", (code, signal) => {
2556
2556
  cleanup();
2557
- resolve2({ code, signal });
2557
+ resolve3({ code, signal });
2558
2558
  });
2559
2559
  spawned.on("error", (err) => {
2560
2560
  cleanup();
2561
- resolve2({ error: err });
2561
+ resolve3({ error: err });
2562
2562
  });
2563
2563
  if (spawned.stdin) {
2564
2564
  spawned.stdin.on("error", (err) => {
2565
2565
  cleanup();
2566
- resolve2({ error: err });
2566
+ resolve3({ error: err });
2567
2567
  });
2568
2568
  }
2569
2569
  });
@@ -2751,14 +2751,14 @@ var require_get_port = __commonJS({
2751
2751
  };
2752
2752
  var releaseOldLockedPortsIntervalMs = 1e3 * 15;
2753
2753
  var interval;
2754
- var getAvailablePort = (options) => new Promise((resolve2, reject) => {
2754
+ var getAvailablePort = (options) => new Promise((resolve3, reject) => {
2755
2755
  const server = net.createServer();
2756
2756
  server.unref();
2757
2757
  server.on("error", reject);
2758
2758
  server.listen(options, () => {
2759
2759
  const { port } = server.address();
2760
2760
  server.close(() => {
2761
- resolve2(port);
2761
+ resolve3(port);
2762
2762
  });
2763
2763
  });
2764
2764
  });
@@ -2830,7 +2830,7 @@ var require_is_port_reachable = __commonJS({
2830
2830
  "use strict";
2831
2831
  var net = require("net");
2832
2832
  module2.exports = async (port, { timeout = 1e3, host } = {}) => {
2833
- const promise = new Promise((resolve2, reject) => {
2833
+ const promise = new Promise((resolve3, reject) => {
2834
2834
  const socket = new net.Socket();
2835
2835
  const onError = () => {
2836
2836
  socket.destroy();
@@ -2841,7 +2841,7 @@ var require_is_port_reachable = __commonJS({
2841
2841
  socket.once("timeout", onError);
2842
2842
  socket.connect(port, host, () => {
2843
2843
  socket.end();
2844
- resolve2();
2844
+ resolve3();
2845
2845
  });
2846
2846
  });
2847
2847
  try {
@@ -2862,7 +2862,6 @@ __export(src_exports, {
2862
2862
  downloadFilesInWorkPath: () => downloadFilesInWorkPath,
2863
2863
  installRequirement: () => installRequirement,
2864
2864
  installRequirementsFile: () => installRequirementsFile,
2865
- prepareCache: () => prepareCache,
2866
2865
  runFrameworkHook: () => runFrameworkHook,
2867
2866
  shouldServe: () => shouldServe,
2868
2867
  startDevServer: () => startDevServer,
@@ -2904,19 +2903,14 @@ var import_build_utils = require("@vercel/build-utils");
2904
2903
  var UV_VERSION = "0.9.22";
2905
2904
  var UV_PYTHON_PATH_PREFIX = "/uv/python/";
2906
2905
  var UV_PYTHON_DOWNLOADS_MODE = "automatic";
2907
- var UV_CACHE_DIR_SUBPATH = [".vercel", "python", "cache", "uv"];
2908
2906
  var isWin = process.platform === "win32";
2909
2907
  var uvExec = isWin ? "uv.exe" : "uv";
2910
2908
  function findUvInPath() {
2911
2909
  return import_which.default.sync("uv", { nothrow: true });
2912
2910
  }
2913
- function getUvCacheDir(workPath) {
2914
- return (0, import_path.join)(workPath, ...UV_CACHE_DIR_SUBPATH);
2915
- }
2916
2911
  var UvRunner = class {
2917
- constructor(uvPath, uvCacheDir) {
2912
+ constructor(uvPath) {
2918
2913
  this.uvPath = uvPath;
2919
- this.uvCacheDir = uvCacheDir;
2920
2914
  }
2921
2915
  getPath() {
2922
2916
  return this.uvPath;
@@ -2993,7 +2987,7 @@ var UvRunner = class {
2993
2987
  try {
2994
2988
  await (0, import_execa.default)(this.uvPath, args, {
2995
2989
  cwd: projectDir,
2996
- env: getProtectedUvEnv(process.env, this.uvCacheDir)
2990
+ env: getProtectedUvEnv(process.env)
2997
2991
  });
2998
2992
  } catch (err) {
2999
2993
  const error = new Error(
@@ -3058,7 +3052,7 @@ var UvRunner = class {
3058
3052
  const binDir = isWin ? (0, import_path.join)(venvPath, "Scripts") : (0, import_path.join)(venvPath, "bin");
3059
3053
  const existingPath = process.env.PATH || "";
3060
3054
  return {
3061
- ...getProtectedUvEnv(process.env, this.uvCacheDir),
3055
+ ...getProtectedUvEnv(process.env),
3062
3056
  VIRTUAL_ENV: venvPath,
3063
3057
  PATH: existingPath ? `${binDir}${import_path2.delimiter}${existingPath}` : binDir
3064
3058
  };
@@ -3165,15 +3159,11 @@ async function getUvBinaryOrInstall(pythonPath) {
3165
3159
  function filterUnsafeUvPipArgs(args) {
3166
3160
  return args.filter((arg) => arg !== "--no-warn-script-location");
3167
3161
  }
3168
- function getProtectedUvEnv(baseEnv = process.env, uvCacheDir) {
3169
- const env = {
3162
+ function getProtectedUvEnv(baseEnv = process.env) {
3163
+ return {
3170
3164
  ...baseEnv,
3171
3165
  UV_PYTHON_DOWNLOADS: UV_PYTHON_DOWNLOADS_MODE
3172
3166
  };
3173
- if (uvCacheDir) {
3174
- env.UV_CACHE_DIR = uvCacheDir;
3175
- }
3176
- return env;
3177
3167
  }
3178
3168
  var UV_BUNDLE_DIR = "_uv";
3179
3169
  async function getUvBinaryForBundling(pythonPath) {
@@ -3212,9 +3202,9 @@ function useVirtualEnv(workPath, env, systemPython) {
3212
3202
  }
3213
3203
  return { pythonCmd };
3214
3204
  }
3215
- function createVenvEnv(venvPath, baseEnv = process.env, uvCacheDir) {
3205
+ function createVenvEnv(venvPath, baseEnv = process.env) {
3216
3206
  const env = {
3217
- ...getProtectedUvEnv(baseEnv, uvCacheDir),
3207
+ ...getProtectedUvEnv(baseEnv),
3218
3208
  VIRTUAL_ENV: venvPath
3219
3209
  };
3220
3210
  const binDir = getVenvBinDir(venvPath);
@@ -3226,7 +3216,6 @@ async function ensureVenv({
3226
3216
  pythonPath,
3227
3217
  venvPath,
3228
3218
  uvPath,
3229
- uvCacheDir,
3230
3219
  quiet
3231
3220
  }) {
3232
3221
  const marker = (0, import_path3.join)(venvPath, "pyvenv.cfg");
@@ -3240,9 +3229,7 @@ async function ensureVenv({
3240
3229
  console.log(`Creating virtual environment at "${venvPath}"...`);
3241
3230
  }
3242
3231
  if (uvPath) {
3243
- await (0, import_execa2.default)(uvPath, ["venv", venvPath], {
3244
- env: getProtectedUvEnv(process.env, uvCacheDir)
3245
- });
3232
+ await (0, import_execa2.default)(uvPath, ["venv", venvPath]);
3246
3233
  } else {
3247
3234
  await (0, import_execa2.default)(pythonPath, ["-m", "venv", venvPath]);
3248
3235
  }
@@ -3749,7 +3736,7 @@ async function pipInstall(pipPath, uvPath, workPath, args, targetDir) {
3749
3736
  try {
3750
3737
  await (0, import_execa3.default)(uvPath, uvArgs, {
3751
3738
  cwd: workPath,
3752
- env: getProtectedUvEnv(process.env, getUvCacheDir(workPath))
3739
+ env: getProtectedUvEnv()
3753
3740
  });
3754
3741
  return;
3755
3742
  } catch (err) {
@@ -3831,7 +3818,7 @@ var import_build_utils5 = require("@vercel/build-utils");
3831
3818
  var import_python_analysis3 = require("@vercel/python-analysis");
3832
3819
  var readFile = (0, import_util.promisify)(import_fs4.default.readFile);
3833
3820
  var LAMBDA_SIZE_THRESHOLD_BYTES = 249 * 1024 * 1024;
3834
- var LAMBDA_PACKING_TARGET_BYTES = 245 * 1024 * 1024;
3821
+ var LAMBDA_PACKING_TARGET_BYTES = 240 * 1024 * 1024;
3835
3822
  var LAMBDA_EPHEMERAL_STORAGE_BYTES = 500 * 1024 * 1024;
3836
3823
  var PythonDependencyExternalizer = class {
3837
3824
  constructor(options) {
@@ -4403,7 +4390,7 @@ function createLogListener(callback, stream) {
4403
4390
  };
4404
4391
  }
4405
4392
  function sleep(ms) {
4406
- return new Promise((resolve2) => setTimeout(resolve2, ms));
4393
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
4407
4394
  }
4408
4395
  async function checkForPort(port, timeout) {
4409
4396
  const start = Date.now();
@@ -4533,7 +4520,7 @@ async function runSync({
4533
4520
  (0, import_build_utils8.debug)(`Unknown manifest type: ${manifestType}`);
4534
4521
  return;
4535
4522
  }
4536
- await new Promise((resolve2, reject) => {
4523
+ await new Promise((resolve3, reject) => {
4537
4524
  (0, import_build_utils8.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
4538
4525
  const child = (0, import_child_process2.spawn)(spawnCmd, spawnArgs, {
4539
4526
  cwd: projectDir,
@@ -4557,7 +4544,7 @@ async function runSync({
4557
4544
  child.on("error", reject);
4558
4545
  child.on("exit", (code, signal) => {
4559
4546
  if (code === 0) {
4560
- resolve2();
4547
+ resolve3();
4561
4548
  } else {
4562
4549
  reject(
4563
4550
  new Error(
@@ -4605,7 +4592,7 @@ async function installVercelRuntime({
4605
4592
  );
4606
4593
  const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
4607
4594
  const spawnArgs = [...pip.prefix, "--target", targetDir, runtimeDep];
4608
- await new Promise((resolve2, reject) => {
4595
+ await new Promise((resolve3, reject) => {
4609
4596
  const child = (0, import_child_process2.spawn)(pip.cmd, spawnArgs, {
4610
4597
  cwd: workPath,
4611
4598
  env: getProtectedUvEnv(env),
@@ -4628,7 +4615,7 @@ async function installVercelRuntime({
4628
4615
  child.on("error", reject);
4629
4616
  child.on("exit", (code, signal) => {
4630
4617
  if (code === 0) {
4631
- resolve2();
4618
+ resolve3();
4632
4619
  } else {
4633
4620
  reject(
4634
4621
  new Error(
@@ -4716,12 +4703,7 @@ async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath)
4716
4703
  return { command: pythonCmd, args: [] };
4717
4704
  }
4718
4705
  const venvPath = (0, import_path8.join)(workPath, ".venv");
4719
- await ensureVenv({
4720
- pythonPath: systemPython,
4721
- venvPath,
4722
- uvPath,
4723
- quiet: true
4724
- });
4706
+ await ensureVenv({ pythonPath: systemPython, venvPath, uvPath, quiet: true });
4725
4707
  (0, import_build_utils8.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
4726
4708
  const pythonBin = getVenvPythonBin(venvPath);
4727
4709
  const binDir = getVenvBinDir(venvPath);
@@ -4799,8 +4781,8 @@ var startDevServer = async (opts) => {
4799
4781
  let resolveChildReady;
4800
4782
  let rejectChildReady;
4801
4783
  const childReady = new Promise(
4802
- (resolve2, reject) => {
4803
- resolveChildReady = resolve2;
4784
+ (resolve3, reject) => {
4785
+ resolveChildReady = resolve3;
4804
4786
  rejectChildReady = reject;
4805
4787
  }
4806
4788
  );
@@ -5421,24 +5403,109 @@ async function runQuirks(ctx) {
5421
5403
  }
5422
5404
 
5423
5405
  // src/django.ts
5424
- var import_fs9 = require("fs");
5406
+ var import_fs9 = __toESM(require("fs"));
5425
5407
  var import_path11 = require("path");
5426
5408
  var import_execa5 = __toESM(require_execa());
5427
5409
  var import_build_utils12 = require("@vercel/build-utils");
5428
5410
  var scriptPath = (0, import_path11.join)(__dirname, "..", "templates", "vc_django_settings.py");
5429
- var script = (0, import_fs9.readFileSync)(scriptPath, "utf-8");
5411
+ var script = import_fs9.default.readFileSync(scriptPath, "utf-8");
5430
5412
  async function getDjangoSettings(projectDir, env) {
5431
5413
  try {
5432
5414
  const { stdout } = await (0, import_execa5.default)("python", ["-c", script], {
5433
5415
  env,
5434
5416
  cwd: projectDir
5435
5417
  });
5436
- return JSON.parse(stdout);
5418
+ const parsed = JSON.parse(stdout);
5419
+ if (!parsed)
5420
+ return null;
5421
+ return {
5422
+ settingsModule: parsed.settings_module,
5423
+ djangoSettings: parsed.django_settings
5424
+ };
5437
5425
  } catch (err) {
5438
5426
  (0, import_build_utils12.debug)(`Django hook: failed to discover settings from manage.py: ${err}`);
5439
5427
  return null;
5440
5428
  }
5441
5429
  }
5430
+ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir, settingsModule, djangoSettings) {
5431
+ const pythonPath = getVenvPythonBin(venvPath);
5432
+ const storages = djangoSettings["STORAGES"];
5433
+ const storageBackend = storages?.staticfiles?.BACKEND ?? djangoSettings["STATICFILES_STORAGE"] ?? "django.contrib.staticfiles.storage.StaticFilesStorage";
5434
+ const staticUrl = djangoSettings["STATIC_URL"] ?? "/static/";
5435
+ const staticRoot = djangoSettings["STATIC_ROOT"] != null ? String(djangoSettings["STATIC_ROOT"]) : null;
5436
+ const whitenoiseUseFinders = djangoSettings["WHITENOISE_USE_FINDERS"] === true;
5437
+ const installedApps = djangoSettings["INSTALLED_APPS"] ?? [];
5438
+ const staticfilesDirs = djangoSettings["STATICFILES_DIRS"] ?? [];
5439
+ const staticSourceDirs = [
5440
+ ...installedApps.map((app) => (0, import_path11.join)(workPath, ...app.split("."), "static")),
5441
+ // TODO: Deal with optional prefixes in STATICFILES_DIRS.
5442
+ ...staticfilesDirs.map((d) => Array.isArray(d) ? d[1] : d)
5443
+ ].filter((d) => import_fs9.default.existsSync(d));
5444
+ if (storageBackend.startsWith("storages.backends.")) {
5445
+ console.log(
5446
+ "django-storages detected \u2014 running collectstatic with original settings"
5447
+ );
5448
+ await (0, import_execa5.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
5449
+ env: { ...env, DJANGO_SETTINGS_MODULE: settingsModule },
5450
+ cwd: workPath
5451
+ });
5452
+ return {
5453
+ staticSourceDirs,
5454
+ staticRoot: staticRoot ? (0, import_path11.resolve)(workPath, staticRoot) : null,
5455
+ manifestRelPath: null
5456
+ };
5457
+ }
5458
+ if (!staticRoot && !whitenoiseUseFinders) {
5459
+ console.log(
5460
+ "No collectstatic strategy configured \u2014 skipping collectstatic"
5461
+ );
5462
+ return null;
5463
+ }
5464
+ const staticUrlPath = staticUrl.replace(/^\/|\/$/g, "") || "static";
5465
+ const staticOutputDir = (0, import_path11.join)(outputStaticDir, staticUrlPath);
5466
+ await import_fs9.default.promises.mkdir(staticOutputDir, { recursive: true });
5467
+ const shimPath = (0, import_path11.join)(workPath, "_vercel_collectstatic_settings.py");
5468
+ const shimLines = [
5469
+ `from ${settingsModule} import *`,
5470
+ `STATIC_ROOT = ${JSON.stringify(staticOutputDir)}`
5471
+ ];
5472
+ if (whitenoiseUseFinders) {
5473
+ shimLines.push(`WHITENOISE_USE_FINDERS = False`);
5474
+ }
5475
+ await import_fs9.default.promises.writeFile(shimPath, shimLines.join("\n") + "\n");
5476
+ try {
5477
+ console.log("Running collectstatic...");
5478
+ await (0, import_execa5.default)(pythonPath, ["manage.py", "collectstatic", "--noinput"], {
5479
+ env: {
5480
+ ...env,
5481
+ DJANGO_SETTINGS_MODULE: "_vercel_collectstatic_settings"
5482
+ },
5483
+ cwd: workPath
5484
+ });
5485
+ } finally {
5486
+ await import_fs9.default.promises.unlink(shimPath).catch(() => {
5487
+ });
5488
+ }
5489
+ const MANIFEST_STORAGE_BACKENDS = [
5490
+ "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
5491
+ "whitenoise.storage.CompressedManifestStaticFilesStorage"
5492
+ ];
5493
+ let manifestRelPath = null;
5494
+ if (MANIFEST_STORAGE_BACKENDS.includes(storageBackend) && staticRoot) {
5495
+ const manifestSrc = (0, import_path11.join)(staticOutputDir, "staticfiles.json");
5496
+ const resolvedStaticRoot = (0, import_path11.resolve)(workPath, staticRoot);
5497
+ const manifestDest = (0, import_path11.join)(resolvedStaticRoot, "staticfiles.json");
5498
+ await import_fs9.default.promises.mkdir(resolvedStaticRoot, { recursive: true });
5499
+ await import_fs9.default.promises.copyFile(manifestSrc, manifestDest);
5500
+ manifestRelPath = (0, import_path11.relative)(workPath, manifestDest);
5501
+ (0, import_build_utils12.debug)(`Copied staticfiles.json to ${manifestDest} for Lambda bundle`);
5502
+ }
5503
+ return {
5504
+ staticSourceDirs,
5505
+ staticRoot: staticRoot ? (0, import_path11.resolve)(workPath, staticRoot) : null,
5506
+ manifestRelPath
5507
+ };
5508
+ }
5442
5509
 
5443
5510
  // src/index.ts
5444
5511
  var import_python_analysis7 = require("@vercel/python-analysis");
@@ -5449,30 +5516,47 @@ async function runFrameworkHook(framework, ctx) {
5449
5516
  return hook?.(ctx);
5450
5517
  }
5451
5518
  var frameworkHooks = {
5452
- django: async ({ pythonEnv, projectDir, detected }) => {
5519
+ django: async ({
5520
+ pythonEnv,
5521
+ projectDir,
5522
+ workPath,
5523
+ venvPath,
5524
+ detected
5525
+ }) => {
5453
5526
  if (detected?.baseDir === void 0) {
5454
5527
  (0, import_build_utils13.debug)("Django hook: no manage.py detected, skipping");
5455
5528
  return;
5456
5529
  }
5457
- const settings = await getDjangoSettings(projectDir, pythonEnv);
5458
- (0, import_build_utils13.debug)(`Django settings: ${JSON.stringify(settings)}`);
5459
- if (!settings)
5530
+ const settingsResult = await getDjangoSettings(projectDir, pythonEnv);
5531
+ (0, import_build_utils13.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
5532
+ if (!settingsResult)
5460
5533
  return;
5534
+ const { djangoSettings, settingsModule } = settingsResult;
5535
+ let entrypoint;
5461
5536
  const baseDir = detected?.baseDir ?? "";
5462
- const asgiApp = settings["ASGI_APPLICATION"];
5537
+ const asgiApp = djangoSettings["ASGI_APPLICATION"];
5463
5538
  if (typeof asgiApp === "string") {
5464
5539
  const rel = `${asgiApp.split(".").slice(0, -1).join("/")}.py`;
5465
- const entrypoint = baseDir ? `${baseDir}/${rel}` : rel;
5540
+ entrypoint = baseDir ? `${baseDir}/${rel}` : rel;
5466
5541
  (0, import_build_utils13.debug)(`Django hook: ASGI entrypoint: ${entrypoint}`);
5467
- return { entrypoint };
5468
- }
5469
- const wsgiApp = settings["WSGI_APPLICATION"];
5470
- if (typeof wsgiApp === "string") {
5471
- const rel = `${wsgiApp.split(".").slice(0, -1).join("/")}.py`;
5472
- const entrypoint = baseDir ? `${baseDir}/${rel}` : rel;
5473
- (0, import_build_utils13.debug)(`Django hook: WSGI entrypoint: ${entrypoint}`);
5474
- return { entrypoint };
5542
+ } else {
5543
+ const wsgiApp = djangoSettings["WSGI_APPLICATION"];
5544
+ if (typeof wsgiApp === "string") {
5545
+ const rel = `${wsgiApp.split(".").slice(0, -1).join("/")}.py`;
5546
+ entrypoint = baseDir ? `${baseDir}/${rel}` : rel;
5547
+ (0, import_build_utils13.debug)(`Django hook: WSGI entrypoint: ${entrypoint}`);
5548
+ }
5475
5549
  }
5550
+ const outputStaticDir = (0, import_path12.join)(workPath, ".vercel", "output", "static");
5551
+ const djangoStatic = await runDjangoCollectStatic(
5552
+ venvPath,
5553
+ workPath,
5554
+ pythonEnv,
5555
+ outputStaticDir,
5556
+ settingsModule,
5557
+ djangoSettings
5558
+ );
5559
+ return { entrypoint, djangoStatic };
5476
5560
  }
5477
5561
  };
5478
5562
  async function downloadFilesInWorkPath({
@@ -5584,12 +5668,10 @@ var build = async ({
5584
5668
  }
5585
5669
  fsFiles = await (0, import_build_utils13.glob)("**", workPath);
5586
5670
  const venvPath = (0, import_path12.join)(workPath, ".vercel", "python", ".venv");
5587
- const uvCacheDir = getUvCacheDir(workPath);
5588
5671
  await builderSpan.child("vc.builder.python.venv").trace(async () => {
5589
5672
  await ensureVenv({
5590
5673
  pythonPath: pythonVersion.pythonPath,
5591
- venvPath,
5592
- uvCacheDir
5674
+ venvPath
5593
5675
  });
5594
5676
  });
5595
5677
  if ((0, import_build_utils13.isPythonFramework)(framework)) {
@@ -5618,14 +5700,14 @@ var build = async ({
5618
5700
  }
5619
5701
  }
5620
5702
  const baseEnv = spawnEnv || process.env;
5621
- const pythonEnv = createVenvEnv(venvPath, baseEnv, uvCacheDir);
5703
+ const pythonEnv = createVenvEnv(venvPath, baseEnv);
5622
5704
  pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
5623
5705
  let assumeDepsInstalled = false;
5624
5706
  let uv;
5625
5707
  try {
5626
5708
  const uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
5627
5709
  console.log(`Using uv at "${uvPath}"`);
5628
- uv = new UvRunner(uvPath, uvCacheDir);
5710
+ uv = new UvRunner(uvPath);
5629
5711
  } catch (err) {
5630
5712
  console.log("Failed to install or locate uv");
5631
5713
  throw new Error(
@@ -5722,6 +5804,8 @@ var build = async ({
5722
5804
  const hookResult = await runFrameworkHook(framework, {
5723
5805
  pythonEnv,
5724
5806
  projectDir: (0, import_path12.join)(workPath, entryDirectory),
5807
+ workPath,
5808
+ venvPath,
5725
5809
  entrypoint,
5726
5810
  detected
5727
5811
  });
@@ -5732,6 +5816,7 @@ var build = async ({
5732
5816
  if (entrypointNotFound) {
5733
5817
  throw entrypointNotFound;
5734
5818
  }
5819
+ const djangoStatic = hookResult?.djangoStatic ?? null;
5735
5820
  const runtimeDep = baseEnv.VERCEL_RUNTIME_PYTHON || `vercel-runtime==${VERCEL_RUNTIME_VERSION}`;
5736
5821
  (0, import_build_utils13.debug)(`Installing ${runtimeDep}`);
5737
5822
  await uv.pip({
@@ -5828,6 +5913,18 @@ from vercel_runtime.vc_init import vc_handler
5828
5913
  "**/yarn.lock",
5829
5914
  "**/package-lock.json"
5830
5915
  ];
5916
+ if (djangoStatic) {
5917
+ const dirsToExclude = [
5918
+ ...djangoStatic.staticSourceDirs,
5919
+ ...djangoStatic.staticRoot ? [djangoStatic.staticRoot] : []
5920
+ ];
5921
+ for (const absDir of dirsToExclude) {
5922
+ const rel = (0, import_path12.relative)(workPath, absDir);
5923
+ if (!rel.startsWith("..")) {
5924
+ predefinedExcludes.push(`${rel}/**`);
5925
+ }
5926
+ }
5927
+ }
5831
5928
  const lambdaEnv = {};
5832
5929
  lambdaEnv.PYTHONPATH = vendorDir;
5833
5930
  Object.assign(lambdaEnv, quirksResult.env);
@@ -5836,6 +5933,11 @@ from vercel_runtime.vc_init import vc_handler
5836
5933
  ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
5837
5934
  };
5838
5935
  const files = await (0, import_build_utils13.glob)("**", globOptions);
5936
+ if (djangoStatic?.manifestRelPath) {
5937
+ files[djangoStatic.manifestRelPath] = new import_build_utils13.FileFsRef({
5938
+ fsPath: (0, import_path12.join)(workPath, djangoStatic.manifestRelPath)
5939
+ });
5940
+ }
5839
5941
  const depExternalizer = new PythonDependencyExternalizer({
5840
5942
  venvPath,
5841
5943
  vendorDir,
@@ -5882,41 +5984,6 @@ from vercel_runtime.vc_init import vc_handler
5882
5984
  });
5883
5985
  return { output };
5884
5986
  };
5885
- async function readBuildOutputV3Config(workPath) {
5886
- try {
5887
- const configPath = (0, import_path12.join)(workPath, ".vercel", "output", "config.json");
5888
- return JSON.parse(await import_fs10.default.promises.readFile(configPath, "utf8"));
5889
- } catch (err) {
5890
- if (err.code !== "ENOENT") {
5891
- throw err;
5892
- }
5893
- }
5894
- return void 0;
5895
- }
5896
- var prepareCache = async ({
5897
- repoRootPath,
5898
- workPath
5899
- }) => {
5900
- const cacheFiles = {};
5901
- const root = repoRootPath || workPath;
5902
- const ignore = ["**/*.pyc", "**/__pycache__/**"];
5903
- const configV3 = await readBuildOutputV3Config(workPath);
5904
- if (configV3?.cache && Array.isArray(configV3.cache)) {
5905
- for (const cacheGlob of configV3.cache) {
5906
- Object.assign(cacheFiles, await (0, import_build_utils13.glob)(cacheGlob, workPath));
5907
- }
5908
- return cacheFiles;
5909
- }
5910
- Object.assign(
5911
- cacheFiles,
5912
- await (0, import_build_utils13.glob)("**/.vercel/python/.venv/**", { cwd: root, ignore })
5913
- );
5914
- Object.assign(
5915
- cacheFiles,
5916
- await (0, import_build_utils13.glob)("**/.vercel/python/cache/uv/**", { cwd: root, ignore })
5917
- );
5918
- return cacheFiles;
5919
- };
5920
5987
  var shouldServe = (opts) => {
5921
5988
  const framework = opts.config.framework;
5922
5989
  if ((0, import_build_utils13.isPythonFramework)(framework)) {
@@ -5954,7 +6021,6 @@ function hasProp(obj, key) {
5954
6021
  downloadFilesInWorkPath,
5955
6022
  installRequirement,
5956
6023
  installRequirementsFile,
5957
- prepareCache,
5958
6024
  runFrameworkHook,
5959
6025
  shouldServe,
5960
6026
  startDevServer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "6.22.0",
3
+ "version": "6.23.0",
4
4
  "main": "./dist/index.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -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/python-runtime": "0.7.0",
39
38
  "@vercel/build-utils": "13.8.0",
40
- "@vercel/error-utils": "2.0.3"
39
+ "@vercel/error-utils": "2.0.3",
40
+ "@vercel/python-runtime": "0.7.0"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "node ../../utils/build-builder.mjs",
@@ -33,4 +33,12 @@ else:
33
33
 
34
34
  mod = importlib.import_module(settings_module)
35
35
  settings = {k: getattr(mod, k) for k in dir(mod) if k.isupper()}
36
- print(json.dumps(settings, default=str))
36
+ print(
37
+ json.dumps(
38
+ {
39
+ "settings_module": settings_module,
40
+ "django_settings": settings,
41
+ },
42
+ default=str,
43
+ )
44
+ )