@vercel/python 6.49.0 → 6.50.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 +785 -243
- 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
|
|
51
|
+
var fs16 = 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
|
-
|
|
76
|
+
fs16.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(
|
|
81
|
+
return checkStat(fs16.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
|
|
91
|
+
var fs16 = require("fs");
|
|
92
92
|
function isexe(path, options, cb) {
|
|
93
|
-
|
|
93
|
+
fs16.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(
|
|
98
|
+
return checkStat(fs16.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
|
|
122
|
+
var fs16 = 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
|
|
398
|
+
var fs16 = 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 =
|
|
412
|
-
|
|
413
|
-
|
|
411
|
+
fd = fs16.openSync(command, "r");
|
|
412
|
+
fs16.readSync(fd, buffer, 0, size, 0);
|
|
413
|
+
fs16.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.4/node_modules/pump/index.js"(exports, module2) {
|
|
1896
1896
|
var once = require_once();
|
|
1897
1897
|
var eos = require_end_of_stream();
|
|
1898
|
-
var
|
|
1898
|
+
var fs16;
|
|
1899
1899
|
try {
|
|
1900
|
-
|
|
1900
|
+
fs16 = 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 (!
|
|
1912
|
+
if (!fs16)
|
|
1913
1913
|
return false;
|
|
1914
|
-
return (stream instanceof (
|
|
1914
|
+
return (stream instanceof (fs16.ReadStream || noop) || stream instanceof (fs16.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:
|
|
2654
|
+
var { join: join17, delimiter: delimiter2, sep: sep3, posix } = require("path");
|
|
2655
2655
|
var isWindows = process.platform === "win32";
|
|
2656
2656
|
var rSlash = new RegExp(`[${posix.sep}${sep3 === posix.sep ? "" : sep3}]`.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 +
|
|
2683
|
+
return prefix + join17(pathPart, cmd);
|
|
2684
2684
|
};
|
|
2685
2685
|
var which2 = async (cmd, opt = {}) => {
|
|
2686
2686
|
const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
|
|
@@ -3912,27 +3912,27 @@ var require_process = __commonJS({
|
|
|
3912
3912
|
var require_filesystem = __commonJS({
|
|
3913
3913
|
"../../node_modules/.pnpm/detect-libc@2.1.2/node_modules/detect-libc/lib/filesystem.js"(exports, module2) {
|
|
3914
3914
|
"use strict";
|
|
3915
|
-
var
|
|
3915
|
+
var fs16 = require("fs");
|
|
3916
3916
|
var LDD_PATH = "/usr/bin/ldd";
|
|
3917
3917
|
var SELF_PATH = "/proc/self/exe";
|
|
3918
3918
|
var MAX_LENGTH = 2048;
|
|
3919
3919
|
var readFileSync2 = (path) => {
|
|
3920
|
-
const fd =
|
|
3920
|
+
const fd = fs16.openSync(path, "r");
|
|
3921
3921
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
3922
|
-
const bytesRead =
|
|
3923
|
-
|
|
3922
|
+
const bytesRead = fs16.readSync(fd, buffer, 0, MAX_LENGTH, 0);
|
|
3923
|
+
fs16.close(fd, () => {
|
|
3924
3924
|
});
|
|
3925
3925
|
return buffer.subarray(0, bytesRead);
|
|
3926
3926
|
};
|
|
3927
3927
|
var readFile2 = (path) => new Promise((resolve3, reject) => {
|
|
3928
|
-
|
|
3928
|
+
fs16.open(path, "r", (err, fd) => {
|
|
3929
3929
|
if (err) {
|
|
3930
3930
|
reject(err);
|
|
3931
3931
|
} else {
|
|
3932
3932
|
const buffer = Buffer.alloc(MAX_LENGTH);
|
|
3933
|
-
|
|
3933
|
+
fs16.read(fd, buffer, 0, MAX_LENGTH, 0, (_, bytesRead) => {
|
|
3934
3934
|
resolve3(buffer.subarray(0, bytesRead));
|
|
3935
|
-
|
|
3935
|
+
fs16.close(fd, () => {
|
|
3936
3936
|
});
|
|
3937
3937
|
});
|
|
3938
3938
|
}
|
|
@@ -4361,6 +4361,8 @@ var require_is_port_reachable = __commonJS({
|
|
|
4361
4361
|
// src/index.ts
|
|
4362
4362
|
var src_exports = {};
|
|
4363
4363
|
__export(src_exports, {
|
|
4364
|
+
addCollectedVendorBytecode: () => addCollectedVendorBytecode,
|
|
4365
|
+
addVendorBytecodeInTiers: () => addVendorBytecodeInTiers,
|
|
4364
4366
|
build: () => build,
|
|
4365
4367
|
defaultShouldServe: () => defaultShouldServe,
|
|
4366
4368
|
detectEntrypoint: () => detectEntrypoint,
|
|
@@ -4377,15 +4379,15 @@ __export(src_exports, {
|
|
|
4377
4379
|
});
|
|
4378
4380
|
module.exports = __toCommonJS(src_exports);
|
|
4379
4381
|
var import_assert = __toESM(require("assert"));
|
|
4380
|
-
var
|
|
4381
|
-
var
|
|
4382
|
+
var import_fs17 = __toESM(require("fs"));
|
|
4383
|
+
var import_path17 = require("path");
|
|
4382
4384
|
|
|
4383
4385
|
// src/package-versions.ts
|
|
4384
4386
|
var VERCEL_RUNTIME_VERSION = "0.16.0";
|
|
4385
4387
|
var VERCEL_WORKERS_VERSION = "0.0.25";
|
|
4386
4388
|
|
|
4387
4389
|
// src/index.ts
|
|
4388
|
-
var
|
|
4390
|
+
var import_build_utils20 = require("@vercel/build-utils");
|
|
4389
4391
|
|
|
4390
4392
|
// src/install.ts
|
|
4391
4393
|
var import_execa3 = __toESM(require_execa());
|
|
@@ -5651,6 +5653,8 @@ var import_build_utils6 = require("@vercel/build-utils");
|
|
|
5651
5653
|
var import_fs5 = __toESM(require("fs"));
|
|
5652
5654
|
var import_path6 = require("path");
|
|
5653
5655
|
var COMPILEALL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
5656
|
+
var PYCACHE_PREFIX_DIR = "_vc_pycache";
|
|
5657
|
+
var RUNTIME_PYCACHE_PREFIX = `/var/task/${PYCACHE_PREFIX_DIR}`;
|
|
5654
5658
|
function isCompileAllFlagEnabled() {
|
|
5655
5659
|
const val = process.env.VERCEL_PYTHON_COMPILEALL;
|
|
5656
5660
|
if (val === void 0 || val === "")
|
|
@@ -5675,7 +5679,8 @@ async function runCompileAll({
|
|
|
5675
5679
|
pythonBin,
|
|
5676
5680
|
filesOrDirectories,
|
|
5677
5681
|
env,
|
|
5678
|
-
excludeRegex
|
|
5682
|
+
excludeRegex,
|
|
5683
|
+
pycachePrefix
|
|
5679
5684
|
}) {
|
|
5680
5685
|
if (filesOrDirectories.length === 0)
|
|
5681
5686
|
return;
|
|
@@ -5691,9 +5696,11 @@ async function runCompileAll({
|
|
|
5691
5696
|
...excludeRegex ? ["-x", excludeRegex] : [],
|
|
5692
5697
|
...filesOrDirectories
|
|
5693
5698
|
];
|
|
5699
|
+
const baseEnv = env || process.env;
|
|
5700
|
+
const subprocessEnv = pycachePrefix ? { ...baseEnv, PYTHONPYCACHEPREFIX: pycachePrefix } : baseEnv;
|
|
5694
5701
|
try {
|
|
5695
5702
|
await (0, import_execa4.default)(pythonBin, args, {
|
|
5696
|
-
env:
|
|
5703
|
+
env: subprocessEnv,
|
|
5697
5704
|
timeout: COMPILEALL_TIMEOUT_MS
|
|
5698
5705
|
});
|
|
5699
5706
|
} catch (err) {
|
|
@@ -5708,6 +5715,42 @@ function derivePycPath(pyRelPath, pythonMajor, pythonMinor) {
|
|
|
5708
5715
|
const baseName = pyRelPath.slice(lastSlash + 1, -3);
|
|
5709
5716
|
return `${dir}__pycache__/${baseName}.cpython-${pythonMajor}${pythonMinor}.pyc`;
|
|
5710
5717
|
}
|
|
5718
|
+
function derivePrefixPycRelPath(pyRelPath, pythonMajor, pythonMinor) {
|
|
5719
|
+
if (!pyRelPath.endsWith(".py"))
|
|
5720
|
+
return null;
|
|
5721
|
+
return `${pyRelPath.slice(0, -3)}.cpython-${pythonMajor}${pythonMinor}.pyc`;
|
|
5722
|
+
}
|
|
5723
|
+
function stripPycachePrefixRoot(head) {
|
|
5724
|
+
const pycachePathSeparators = /* @__PURE__ */ new Set(["/", "\\"]);
|
|
5725
|
+
if (head.length > 1 && head[1] === ":" && !pycachePathSeparators.has(head[0])) {
|
|
5726
|
+
head = head.slice(2);
|
|
5727
|
+
}
|
|
5728
|
+
let start = 0;
|
|
5729
|
+
while (start < head.length && pycachePathSeparators.has(head[start])) {
|
|
5730
|
+
start++;
|
|
5731
|
+
}
|
|
5732
|
+
return head.slice(start);
|
|
5733
|
+
}
|
|
5734
|
+
function deriveStagedPycFsPath(stagingDir, srcAbsPath, pythonMajor, pythonMinor) {
|
|
5735
|
+
const rel = derivePrefixPycRelPath(
|
|
5736
|
+
stripPycachePrefixRoot(srcAbsPath),
|
|
5737
|
+
pythonMajor,
|
|
5738
|
+
pythonMinor
|
|
5739
|
+
);
|
|
5740
|
+
if (!rel)
|
|
5741
|
+
return null;
|
|
5742
|
+
return (0, import_path6.join)(stagingDir, rel.replaceAll("/", import_path6.sep));
|
|
5743
|
+
}
|
|
5744
|
+
function derivePrefixPycBundlePath(runtimeAbsPath, pythonMajor, pythonMinor) {
|
|
5745
|
+
const rel = derivePrefixPycRelPath(
|
|
5746
|
+
stripPycachePrefixRoot(runtimeAbsPath),
|
|
5747
|
+
pythonMajor,
|
|
5748
|
+
pythonMinor
|
|
5749
|
+
);
|
|
5750
|
+
if (!rel)
|
|
5751
|
+
return null;
|
|
5752
|
+
return `${PYCACHE_PREFIX_DIR}/${rel}`;
|
|
5753
|
+
}
|
|
5711
5754
|
var COMPILEALL_APP_EXCLUDED_DIRS = [
|
|
5712
5755
|
".git",
|
|
5713
5756
|
".vercel",
|
|
@@ -5729,6 +5772,58 @@ function getCompileAllAppExcludeRegex(workPath) {
|
|
|
5729
5772
|
const excludedDirs = COMPILEALL_APP_EXCLUDED_DIRS.map(escapePythonRegex).join("|");
|
|
5730
5773
|
return `${escapePythonRegex(workPath)}[/\\\\](?:${excludedDirs})(?:[/\\\\]|$)`;
|
|
5731
5774
|
}
|
|
5775
|
+
async function collectAppPrefixBytecodeFiles({
|
|
5776
|
+
stagingDir,
|
|
5777
|
+
workPath,
|
|
5778
|
+
files: appFiles,
|
|
5779
|
+
runtimeTaskRoot,
|
|
5780
|
+
pythonMajor,
|
|
5781
|
+
pythonMinor
|
|
5782
|
+
}) {
|
|
5783
|
+
const pending = [];
|
|
5784
|
+
for (const bundlePath of Object.keys(appFiles)) {
|
|
5785
|
+
if (!bundlePath.endsWith(".py"))
|
|
5786
|
+
continue;
|
|
5787
|
+
const stagedFsPath = deriveStagedPycFsPath(
|
|
5788
|
+
stagingDir,
|
|
5789
|
+
(0, import_path6.join)(workPath, bundlePath.replaceAll("/", import_path6.sep)),
|
|
5790
|
+
pythonMajor,
|
|
5791
|
+
pythonMinor
|
|
5792
|
+
);
|
|
5793
|
+
const pycBundlePath = derivePrefixPycBundlePath(
|
|
5794
|
+
`${runtimeTaskRoot}/${bundlePath}`,
|
|
5795
|
+
pythonMajor,
|
|
5796
|
+
pythonMinor
|
|
5797
|
+
);
|
|
5798
|
+
if (!stagedFsPath || !pycBundlePath)
|
|
5799
|
+
continue;
|
|
5800
|
+
pending.push({ bundlePath: pycBundlePath, srcFsPath: stagedFsPath });
|
|
5801
|
+
}
|
|
5802
|
+
const results = await Promise.all(
|
|
5803
|
+
pending.map(async ({ bundlePath, srcFsPath }) => {
|
|
5804
|
+
try {
|
|
5805
|
+
const stats = await import_fs5.default.promises.stat(srcFsPath);
|
|
5806
|
+
return { bundlePath, srcFsPath, size: stats.size };
|
|
5807
|
+
} catch {
|
|
5808
|
+
return null;
|
|
5809
|
+
}
|
|
5810
|
+
})
|
|
5811
|
+
);
|
|
5812
|
+
const files = {};
|
|
5813
|
+
const perItemSizes = /* @__PURE__ */ new Map();
|
|
5814
|
+
let totalSize = 0;
|
|
5815
|
+
for (const result of results) {
|
|
5816
|
+
if (!result)
|
|
5817
|
+
continue;
|
|
5818
|
+
files[result.bundlePath] = new import_build_utils6.FileFsRef({
|
|
5819
|
+
fsPath: result.srcFsPath,
|
|
5820
|
+
size: result.size
|
|
5821
|
+
});
|
|
5822
|
+
perItemSizes.set(result.bundlePath, result.size);
|
|
5823
|
+
totalSize += result.size;
|
|
5824
|
+
}
|
|
5825
|
+
return { files, totalSize, perItemSizes };
|
|
5826
|
+
}
|
|
5732
5827
|
async function collectAppBytecodeFiles({
|
|
5733
5828
|
workPath,
|
|
5734
5829
|
files: appFiles,
|
|
@@ -5800,6 +5895,8 @@ var LAMBDA_SIZE_THRESHOLD_BYTES = 225 * 1024 * 1024;
|
|
|
5800
5895
|
var BYTECODE_FILL_MARGIN_BYTES = 5 * 1024 * 1024;
|
|
5801
5896
|
var BYTECODE_FILL_CEILING_BYTES = LAMBDA_SIZE_THRESHOLD_BYTES - BYTECODE_FILL_MARGIN_BYTES;
|
|
5802
5897
|
var LAMBDA_EPHEMERAL_STORAGE_BYTES = 500 * 1024 * 1024;
|
|
5898
|
+
var EPHEMERAL_INSTALL_BUDGET_BYTES = LAMBDA_EPHEMERAL_STORAGE_BYTES - 50 * 1024 * 1024;
|
|
5899
|
+
var RUNTIME_DEPS_DIR = "/tmp/_vc_deps";
|
|
5803
5900
|
var MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE = 5 * 1024 * 1024 * 1024;
|
|
5804
5901
|
var BUNDLING_DOCS_LINK = "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled";
|
|
5805
5902
|
var PythonDependencyExternalizer = class {
|
|
@@ -5910,7 +6007,7 @@ application into smaller functions.`,
|
|
|
5910
6007
|
* back to bundling everything for Hive and returns `fellBackToFullBundle:
|
|
5911
6008
|
* true` so the caller can apply the same compileall handling.
|
|
5912
6009
|
*/
|
|
5913
|
-
async generateBundle(files) {
|
|
6010
|
+
async generateBundle(files, options = {}) {
|
|
5914
6011
|
if (!this.analyzed) {
|
|
5915
6012
|
throw new Error(
|
|
5916
6013
|
"PythonDependencyExternalizer.analyze() must be called before generateBundle()"
|
|
@@ -6071,7 +6168,20 @@ To fix this, either:
|
|
|
6071
6168
|
([name]) => externalizableSet.has((0, import_python_analysis3.normalizePackageName)(name))
|
|
6072
6169
|
)
|
|
6073
6170
|
);
|
|
6074
|
-
const bundledPublic =
|
|
6171
|
+
const { packingMode, bundledPublic } = planPublicPackagePacking({
|
|
6172
|
+
publicPackageSizes,
|
|
6173
|
+
zipCapacity: remainingCapacity,
|
|
6174
|
+
bytecodeFirst: options.bytecodeFirst ?? false
|
|
6175
|
+
});
|
|
6176
|
+
if (options.bytecodeFirst && packingMode === "knapsack") {
|
|
6177
|
+
(0, import_build_utils7.debug)(
|
|
6178
|
+
`bytecode-first packing disabled: the public package set exceeds the ephemeral install budget (${(EPHEMERAL_INSTALL_BUDGET_BYTES / (1024 * 1024)).toFixed(2)} MB); falling back to knapsack packing`
|
|
6179
|
+
);
|
|
6180
|
+
}
|
|
6181
|
+
const bundledPublicSet = new Set(bundledPublic.map(import_python_analysis3.normalizePackageName));
|
|
6182
|
+
const externalizedPublic = externalizablePublic.filter(
|
|
6183
|
+
(name) => !bundledPublicSet.has((0, import_python_analysis3.normalizePackageName)(name))
|
|
6184
|
+
);
|
|
6075
6185
|
const allBundledPackages = [...alwaysBundled, ...bundledPublic];
|
|
6076
6186
|
const selectedVendorFiles = await this.mirrorPackagesIntoVendor({
|
|
6077
6187
|
vendorDirName: this.vendorDir,
|
|
@@ -6143,7 +6253,13 @@ functions.`,
|
|
|
6143
6253
|
action: "Learn More"
|
|
6144
6254
|
});
|
|
6145
6255
|
}
|
|
6146
|
-
return {
|
|
6256
|
+
return {
|
|
6257
|
+
fellBackToFullBundle: false,
|
|
6258
|
+
packingMode,
|
|
6259
|
+
alwaysBundledPackages: alwaysBundled,
|
|
6260
|
+
bundledPublicPackages: bundledPublic,
|
|
6261
|
+
externalizedPublicPackages: externalizedPublic
|
|
6262
|
+
};
|
|
6147
6263
|
}
|
|
6148
6264
|
/**
|
|
6149
6265
|
* Discard any runtime-install artifacts added so far and bundle every
|
|
@@ -6456,6 +6572,92 @@ functions.`,
|
|
|
6456
6572
|
);
|
|
6457
6573
|
return { files, totalSize, perItemSizes };
|
|
6458
6574
|
}
|
|
6575
|
+
/**
|
|
6576
|
+
* Collect staged prefix `.pyc` files for vendor packages, keyed under
|
|
6577
|
+
* `_vc_pycache/<runtimeRoot>/...` (`runtimeRoot` = `/var/task/_vendor`
|
|
6578
|
+
* for bundled packages, the /tmp site-packages dir for externalized
|
|
6579
|
+
* ones). Missing staged files are silently skipped. Must be called after
|
|
6580
|
+
* `analyze()`.
|
|
6581
|
+
*/
|
|
6582
|
+
async collectPrefixBytecodeFiles({
|
|
6583
|
+
stagingDir,
|
|
6584
|
+
runtimeRoot,
|
|
6585
|
+
includePackages
|
|
6586
|
+
}) {
|
|
6587
|
+
if (!this.sitePackageDirs || !this.distributions) {
|
|
6588
|
+
throw new Error(
|
|
6589
|
+
"collectPrefixBytecodeFiles() must be called after analyze()"
|
|
6590
|
+
);
|
|
6591
|
+
}
|
|
6592
|
+
if (this.pythonMajor == null || this.pythonMinor == null) {
|
|
6593
|
+
return { files: {}, totalSize: 0, perItemSizes: /* @__PURE__ */ new Map() };
|
|
6594
|
+
}
|
|
6595
|
+
const includeSet = includePackages ? new Set(includePackages.map(import_python_analysis3.normalizePackageName)) : null;
|
|
6596
|
+
const pending = [];
|
|
6597
|
+
for (const dir of this.sitePackageDirs) {
|
|
6598
|
+
const dirDistributions = this.distributions.get(dir);
|
|
6599
|
+
if (!dirDistributions)
|
|
6600
|
+
continue;
|
|
6601
|
+
const resolvedDir = (0, import_path7.resolve)(dir);
|
|
6602
|
+
const dirPrefix = resolvedDir + import_path7.sep;
|
|
6603
|
+
for (const [name, dist] of dirDistributions) {
|
|
6604
|
+
if (includeSet && !includeSet.has(name))
|
|
6605
|
+
continue;
|
|
6606
|
+
for (const { path: rawPath } of dist.files) {
|
|
6607
|
+
if (!rawPath.endsWith(".py"))
|
|
6608
|
+
continue;
|
|
6609
|
+
const filePath = rawPath.replaceAll("/", import_path7.sep);
|
|
6610
|
+
if (!(0, import_path7.resolve)(resolvedDir, filePath).startsWith(dirPrefix)) {
|
|
6611
|
+
continue;
|
|
6612
|
+
}
|
|
6613
|
+
const srcFsPath = deriveStagedPycFsPath(
|
|
6614
|
+
stagingDir,
|
|
6615
|
+
(0, import_path7.join)(dir, filePath),
|
|
6616
|
+
this.pythonMajor,
|
|
6617
|
+
this.pythonMinor
|
|
6618
|
+
);
|
|
6619
|
+
const bundlePath = derivePrefixPycBundlePath(
|
|
6620
|
+
`${runtimeRoot}/${rawPath}`,
|
|
6621
|
+
this.pythonMajor,
|
|
6622
|
+
this.pythonMinor
|
|
6623
|
+
);
|
|
6624
|
+
if (!srcFsPath || !bundlePath)
|
|
6625
|
+
continue;
|
|
6626
|
+
pending.push({ bundlePath, srcFsPath, packageName: name });
|
|
6627
|
+
}
|
|
6628
|
+
}
|
|
6629
|
+
}
|
|
6630
|
+
const results = await Promise.all(
|
|
6631
|
+
pending.map(async ({ bundlePath, srcFsPath, packageName }) => {
|
|
6632
|
+
try {
|
|
6633
|
+
const stats = await import_fs6.default.promises.stat(srcFsPath);
|
|
6634
|
+
return { bundlePath, srcFsPath, size: stats.size, packageName };
|
|
6635
|
+
} catch {
|
|
6636
|
+
return null;
|
|
6637
|
+
}
|
|
6638
|
+
})
|
|
6639
|
+
);
|
|
6640
|
+
const files = {};
|
|
6641
|
+
let totalSize = 0;
|
|
6642
|
+
const perItemSizes = /* @__PURE__ */ new Map();
|
|
6643
|
+
for (const result of results) {
|
|
6644
|
+
if (!result)
|
|
6645
|
+
continue;
|
|
6646
|
+
files[result.bundlePath] = new import_build_utils7.FileFsRef({
|
|
6647
|
+
fsPath: result.srcFsPath,
|
|
6648
|
+
size: result.size
|
|
6649
|
+
});
|
|
6650
|
+
totalSize += result.size;
|
|
6651
|
+
perItemSizes.set(
|
|
6652
|
+
result.packageName,
|
|
6653
|
+
(perItemSizes.get(result.packageName) ?? 0) + result.size
|
|
6654
|
+
);
|
|
6655
|
+
}
|
|
6656
|
+
(0, import_build_utils7.debug)(
|
|
6657
|
+
`Collected ${Object.keys(files).length} prefix bytecode files (${(totalSize / (1024 * 1024)).toFixed(2)} MB) for runtime root ${runtimeRoot}` + (includePackages ? ` from ${includePackages.length} packages` : "")
|
|
6658
|
+
);
|
|
6659
|
+
return { files, totalSize, perItemSizes };
|
|
6660
|
+
}
|
|
6459
6661
|
};
|
|
6460
6662
|
async function getPackagesReachableOnPlatform(lockFile, projectName, pythonMajor, pythonMinor, sysPlatform, platformMachine) {
|
|
6461
6663
|
if (!projectName)
|
|
@@ -6572,6 +6774,23 @@ function lambdaKnapsack(packages, capacity) {
|
|
|
6572
6774
|
}
|
|
6573
6775
|
return bundled;
|
|
6574
6776
|
}
|
|
6777
|
+
function planPublicPackagePacking({
|
|
6778
|
+
publicPackageSizes,
|
|
6779
|
+
zipCapacity,
|
|
6780
|
+
bytecodeFirst
|
|
6781
|
+
}) {
|
|
6782
|
+
let totalPublicSize = 0;
|
|
6783
|
+
for (const size of publicPackageSizes.values()) {
|
|
6784
|
+
totalPublicSize += size;
|
|
6785
|
+
}
|
|
6786
|
+
if (bytecodeFirst && totalPublicSize <= EPHEMERAL_INSTALL_BUDGET_BYTES) {
|
|
6787
|
+
return { packingMode: "bytecode-first", bundledPublic: [] };
|
|
6788
|
+
}
|
|
6789
|
+
return {
|
|
6790
|
+
packingMode: "knapsack",
|
|
6791
|
+
bundledPublic: lambdaKnapsack(publicPackageSizes, zipCapacity)
|
|
6792
|
+
};
|
|
6793
|
+
}
|
|
6575
6794
|
|
|
6576
6795
|
// src/diagnostics.ts
|
|
6577
6796
|
var import_fs7 = __toESM(require("fs"));
|
|
@@ -8674,10 +8893,54 @@ async function runDjangoCollectStatic(venvPath, workPath, djangoPath, env, outpu
|
|
|
8674
8893
|
var import_python_analysis9 = require("@vercel/python-analysis");
|
|
8675
8894
|
|
|
8676
8895
|
// src/subscribers.ts
|
|
8896
|
+
var import_path15 = require("path");
|
|
8897
|
+
var import_fs15 = __toESM(require("fs"));
|
|
8898
|
+
var import_build_utils18 = require("@vercel/build-utils");
|
|
8899
|
+
|
|
8900
|
+
// src/module-entrypoint.ts
|
|
8677
8901
|
var import_path14 = require("path");
|
|
8678
8902
|
var import_fs14 = __toESM(require("fs"));
|
|
8679
|
-
var import_build_utils18 = require("@vercel/build-utils");
|
|
8680
8903
|
var MODULE_ATTR_RE = /^([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*):([A-Za-z_][\w]*)$/;
|
|
8904
|
+
function parseModuleEntrypoint(value) {
|
|
8905
|
+
const match = MODULE_ATTR_RE.exec(value);
|
|
8906
|
+
if (!match) {
|
|
8907
|
+
return null;
|
|
8908
|
+
}
|
|
8909
|
+
return {
|
|
8910
|
+
moduleName: match[1],
|
|
8911
|
+
variableName: match[2],
|
|
8912
|
+
filePath: `${match[1].replace(/\./g, "/")}.py`
|
|
8913
|
+
};
|
|
8914
|
+
}
|
|
8915
|
+
function getModuleEntrypointName({
|
|
8916
|
+
moduleName,
|
|
8917
|
+
variableName
|
|
8918
|
+
}) {
|
|
8919
|
+
return `${moduleName.replace(/\./g, "-")}_${variableName}`;
|
|
8920
|
+
}
|
|
8921
|
+
function safePathSegment(value) {
|
|
8922
|
+
return [...value].map((char) => {
|
|
8923
|
+
if (char === "_") {
|
|
8924
|
+
return "__";
|
|
8925
|
+
}
|
|
8926
|
+
return /[A-Za-z0-9-]/.test(char) ? char : `_${char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`;
|
|
8927
|
+
}).join("");
|
|
8928
|
+
}
|
|
8929
|
+
async function resolveExistingEntrypoint(workPath, filePath) {
|
|
8930
|
+
const candidates = [filePath, filePath.replace(/\.py$/i, "/__init__.py")];
|
|
8931
|
+
for (const candidate of candidates) {
|
|
8932
|
+
try {
|
|
8933
|
+
const stat = await import_fs14.default.promises.stat((0, import_path14.join)(workPath, candidate));
|
|
8934
|
+
if (stat.isFile()) {
|
|
8935
|
+
return candidate;
|
|
8936
|
+
}
|
|
8937
|
+
} catch {
|
|
8938
|
+
}
|
|
8939
|
+
}
|
|
8940
|
+
return null;
|
|
8941
|
+
}
|
|
8942
|
+
|
|
8943
|
+
// src/subscribers.ts
|
|
8681
8944
|
var SUBSCRIBER_OUTPUT_DIR = "_py_subscribers";
|
|
8682
8945
|
var TRIGGER_NUMBER_FIELDS = [
|
|
8683
8946
|
{
|
|
@@ -8710,14 +8973,6 @@ var SUBSCRIBER_FIELD_NAMES = /* @__PURE__ */ new Set([
|
|
|
8710
8973
|
"topics",
|
|
8711
8974
|
...TRIGGER_NUMBER_FIELDS.map(({ field }) => field)
|
|
8712
8975
|
]);
|
|
8713
|
-
function safePathSegment(value) {
|
|
8714
|
-
return [...value].map((char) => {
|
|
8715
|
-
if (char === "_") {
|
|
8716
|
-
return "__";
|
|
8717
|
-
}
|
|
8718
|
-
return /[A-Za-z0-9-]/.test(char) ? char : `_${char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`;
|
|
8719
|
-
}).join("");
|
|
8720
|
-
}
|
|
8721
8976
|
function getSubscriberOutputPath(subscriberName) {
|
|
8722
8977
|
return `${SUBSCRIBER_OUTPUT_DIR}/${safePathSegment(subscriberName)}`;
|
|
8723
8978
|
}
|
|
@@ -8725,8 +8980,8 @@ function getSubscriberConsumerName(subscriberName) {
|
|
|
8725
8980
|
return (0, import_build_utils18.sanitizeConsumerName)(getSubscriberOutputPath(subscriberName));
|
|
8726
8981
|
}
|
|
8727
8982
|
async function getPyprojectSubscribers(workPath) {
|
|
8728
|
-
const pyprojectPath = (0,
|
|
8729
|
-
if (!
|
|
8983
|
+
const pyprojectPath = (0, import_path15.join)(workPath, "pyproject.toml");
|
|
8984
|
+
if (!import_fs15.default.existsSync(pyprojectPath)) {
|
|
8730
8985
|
return [];
|
|
8731
8986
|
}
|
|
8732
8987
|
const pyproject = await (0, import_build_utils18.readConfigFile)(pyprojectPath);
|
|
@@ -8764,8 +9019,13 @@ async function parseSubscriber(workPath, index, config) {
|
|
|
8764
9019
|
if (typeof config.entrypoint !== "string") {
|
|
8765
9020
|
throw subscriberError(`${label} must define string field "entrypoint"`);
|
|
8766
9021
|
}
|
|
8767
|
-
const entrypoint =
|
|
8768
|
-
|
|
9022
|
+
const entrypoint = parseModuleEntrypoint(config.entrypoint);
|
|
9023
|
+
if (!entrypoint) {
|
|
9024
|
+
throw subscriberError(
|
|
9025
|
+
`${label} has invalid entrypoint "${config.entrypoint}". Use "module:object"`
|
|
9026
|
+
);
|
|
9027
|
+
}
|
|
9028
|
+
const name = getModuleEntrypointName(entrypoint);
|
|
8769
9029
|
const existingEntrypoint = await resolveExistingEntrypoint(
|
|
8770
9030
|
workPath,
|
|
8771
9031
|
entrypoint.filePath
|
|
@@ -8784,38 +9044,6 @@ async function parseSubscriber(workPath, index, config) {
|
|
|
8784
9044
|
triggerDefaults: parseTriggerDefaults(name, config)
|
|
8785
9045
|
};
|
|
8786
9046
|
}
|
|
8787
|
-
function getSubscriberName({
|
|
8788
|
-
moduleName,
|
|
8789
|
-
variableName
|
|
8790
|
-
}) {
|
|
8791
|
-
return `${moduleName.replace(/\./g, "-")}_${variableName}`;
|
|
8792
|
-
}
|
|
8793
|
-
function parseEntrypoint(name, value) {
|
|
8794
|
-
const match = MODULE_ATTR_RE.exec(value);
|
|
8795
|
-
if (!match) {
|
|
8796
|
-
throw subscriberError(
|
|
8797
|
-
`subscriber "${name}" has invalid entrypoint "${value}". Use "module:object"`
|
|
8798
|
-
);
|
|
8799
|
-
}
|
|
8800
|
-
return {
|
|
8801
|
-
moduleName: match[1],
|
|
8802
|
-
variableName: match[2],
|
|
8803
|
-
filePath: `${match[1].replace(/\./g, "/")}.py`
|
|
8804
|
-
};
|
|
8805
|
-
}
|
|
8806
|
-
async function resolveExistingEntrypoint(workPath, filePath) {
|
|
8807
|
-
const candidates = [filePath, filePath.replace(/\.py$/i, "/__init__.py")];
|
|
8808
|
-
for (const candidate of candidates) {
|
|
8809
|
-
try {
|
|
8810
|
-
const stat = await import_fs14.default.promises.stat((0, import_path14.join)(workPath, candidate));
|
|
8811
|
-
if (stat.isFile()) {
|
|
8812
|
-
return candidate;
|
|
8813
|
-
}
|
|
8814
|
-
} catch {
|
|
8815
|
-
}
|
|
8816
|
-
}
|
|
8817
|
-
return null;
|
|
8818
|
-
}
|
|
8819
9047
|
function parseTopics(name, value) {
|
|
8820
9048
|
if (!Array.isArray(value) || value.length === 0) {
|
|
8821
9049
|
throw subscriberError(
|
|
@@ -8854,8 +9082,86 @@ function subscriberError(message) {
|
|
|
8854
9082
|
});
|
|
8855
9083
|
}
|
|
8856
9084
|
|
|
9085
|
+
// src/workflows.ts
|
|
9086
|
+
var import_path16 = require("path");
|
|
9087
|
+
var import_fs16 = __toESM(require("fs"));
|
|
9088
|
+
var import_build_utils19 = require("@vercel/build-utils");
|
|
9089
|
+
var WORKFLOW_OUTPUT_DIR = "_py_workflows";
|
|
9090
|
+
var WORKFLOW_TOPIC_PATTERN = "__wkf_*";
|
|
9091
|
+
var WORKFLOW_FIELD_NAMES = /* @__PURE__ */ new Set(["entrypoint"]);
|
|
9092
|
+
function getWorkflowOutputPath(workflowName) {
|
|
9093
|
+
return `${WORKFLOW_OUTPUT_DIR}/${safePathSegment(workflowName)}`;
|
|
9094
|
+
}
|
|
9095
|
+
function getWorkflowConsumerName(workflowName) {
|
|
9096
|
+
return (0, import_build_utils19.sanitizeConsumerName)(getWorkflowOutputPath(workflowName));
|
|
9097
|
+
}
|
|
9098
|
+
async function getPyprojectWorkflows(workPath) {
|
|
9099
|
+
const pyprojectPath = (0, import_path16.join)(workPath, "pyproject.toml");
|
|
9100
|
+
if (!import_fs16.default.existsSync(pyprojectPath)) {
|
|
9101
|
+
return [];
|
|
9102
|
+
}
|
|
9103
|
+
const pyproject = await (0, import_build_utils19.readConfigFile)(pyprojectPath);
|
|
9104
|
+
const workflows = pyproject?.tool?.vercel?.workflows;
|
|
9105
|
+
if (!workflows) {
|
|
9106
|
+
return [];
|
|
9107
|
+
}
|
|
9108
|
+
if (!Array.isArray(workflows)) {
|
|
9109
|
+
throw workflowError('"tool.vercel.workflows" must be an array');
|
|
9110
|
+
}
|
|
9111
|
+
if (workflows.length > 1) {
|
|
9112
|
+
throw workflowError(
|
|
9113
|
+
'"tool.vercel.workflows" must declare a single entrypoint that registers every workflow'
|
|
9114
|
+
);
|
|
9115
|
+
}
|
|
9116
|
+
return Promise.all(
|
|
9117
|
+
workflows.map((config, index) => parseWorkflow(workPath, index, config))
|
|
9118
|
+
);
|
|
9119
|
+
}
|
|
9120
|
+
async function parseWorkflow(workPath, index, config) {
|
|
9121
|
+
const label = `workflow #${index + 1}`;
|
|
9122
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
9123
|
+
throw workflowError(`${label} must be an object`);
|
|
9124
|
+
}
|
|
9125
|
+
for (const key of Object.keys(config)) {
|
|
9126
|
+
if (!WORKFLOW_FIELD_NAMES.has(key)) {
|
|
9127
|
+
throw workflowError(`${label} has unrecognized field "${key}"`);
|
|
9128
|
+
}
|
|
9129
|
+
}
|
|
9130
|
+
if (typeof config.entrypoint !== "string") {
|
|
9131
|
+
throw workflowError(`${label} must define string field "entrypoint"`);
|
|
9132
|
+
}
|
|
9133
|
+
const entrypoint = parseModuleEntrypoint(config.entrypoint);
|
|
9134
|
+
if (!entrypoint) {
|
|
9135
|
+
throw workflowError(
|
|
9136
|
+
`${label} has invalid entrypoint "${config.entrypoint}". Use "module:object"`
|
|
9137
|
+
);
|
|
9138
|
+
}
|
|
9139
|
+
const name = getModuleEntrypointName(entrypoint);
|
|
9140
|
+
const existingEntrypoint = await resolveExistingEntrypoint(
|
|
9141
|
+
workPath,
|
|
9142
|
+
entrypoint.filePath
|
|
9143
|
+
);
|
|
9144
|
+
if (!existingEntrypoint) {
|
|
9145
|
+
throw workflowError(
|
|
9146
|
+
`workflow "${name}" has entrypoint "${config.entrypoint}" but file "${entrypoint.filePath}" does not exist`
|
|
9147
|
+
);
|
|
9148
|
+
}
|
|
9149
|
+
return {
|
|
9150
|
+
name,
|
|
9151
|
+
entrypoint: existingEntrypoint,
|
|
9152
|
+
moduleName: entrypoint.moduleName,
|
|
9153
|
+
variableName: entrypoint.variableName
|
|
9154
|
+
};
|
|
9155
|
+
}
|
|
9156
|
+
function workflowError(message) {
|
|
9157
|
+
return new import_build_utils19.NowBuildError({
|
|
9158
|
+
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
9159
|
+
message
|
|
9160
|
+
});
|
|
9161
|
+
}
|
|
9162
|
+
|
|
8857
9163
|
// src/index.ts
|
|
8858
|
-
var writeFile =
|
|
9164
|
+
var writeFile = import_fs17.default.promises.writeFile;
|
|
8859
9165
|
var PYTHON_ENTRYPOINT_DOCS_URL2 = "https://vercel.com/docs/functions/runtimes/python#python-entrypoints";
|
|
8860
9166
|
var version = -1;
|
|
8861
9167
|
function getDevSubscriberTopics(subscriber) {
|
|
@@ -8871,26 +9177,49 @@ async function getDevSidecars({
|
|
|
8871
9177
|
build: build2
|
|
8872
9178
|
}) {
|
|
8873
9179
|
const framework = build2.config?.framework;
|
|
8874
|
-
if (build2.config?.middleware === true || typeof framework !== "string" || !(0,
|
|
9180
|
+
if (build2.config?.middleware === true || typeof framework !== "string" || !(0, import_build_utils20.isPythonFramework)(framework)) {
|
|
8875
9181
|
return [];
|
|
8876
9182
|
}
|
|
8877
9183
|
const subscribers = await getPyprojectSubscribers(workPath);
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
|
|
8893
|
-
|
|
9184
|
+
const workflows = await getPyprojectWorkflows(workPath);
|
|
9185
|
+
return [
|
|
9186
|
+
...subscribers.map(
|
|
9187
|
+
(subscriber) => ({
|
|
9188
|
+
type: "subscriber",
|
|
9189
|
+
name: subscriber.name,
|
|
9190
|
+
consumer: getSubscriberConsumerName(subscriber.name),
|
|
9191
|
+
workspace: ".",
|
|
9192
|
+
framework,
|
|
9193
|
+
runtime: "python",
|
|
9194
|
+
builder: {
|
|
9195
|
+
use: build2.use,
|
|
9196
|
+
src: subscriber.entrypoint,
|
|
9197
|
+
config: {
|
|
9198
|
+
handlerFunction: subscriber.variableName
|
|
9199
|
+
}
|
|
9200
|
+
},
|
|
9201
|
+
topics: getDevSubscriberTopics(subscriber)
|
|
9202
|
+
})
|
|
9203
|
+
),
|
|
9204
|
+
...workflows.map(
|
|
9205
|
+
(workflow) => ({
|
|
9206
|
+
type: "subscriber",
|
|
9207
|
+
name: workflow.name,
|
|
9208
|
+
consumer: getWorkflowConsumerName(workflow.name),
|
|
9209
|
+
workspace: ".",
|
|
9210
|
+
framework,
|
|
9211
|
+
runtime: "python",
|
|
9212
|
+
builder: {
|
|
9213
|
+
use: build2.use,
|
|
9214
|
+
src: workflow.entrypoint,
|
|
9215
|
+
config: {
|
|
9216
|
+
handlerFunction: workflow.variableName
|
|
9217
|
+
}
|
|
9218
|
+
},
|
|
9219
|
+
topics: [{ topic: WORKFLOW_TOPIC_PATTERN }]
|
|
9220
|
+
})
|
|
9221
|
+
)
|
|
9222
|
+
];
|
|
8894
9223
|
}
|
|
8895
9224
|
function addFiles(target, source) {
|
|
8896
9225
|
for (const [p, f] of Object.entries(source)) {
|
|
@@ -8940,6 +9269,54 @@ async function addVendorBytecodeWithinCapacity({
|
|
|
8940
9269
|
addFiles(files, selectedBytecode.files);
|
|
8941
9270
|
return capacity - selectedBytecode.totalSize;
|
|
8942
9271
|
}
|
|
9272
|
+
async function addVendorBytecodeInTiers({
|
|
9273
|
+
files,
|
|
9274
|
+
depExternalizer,
|
|
9275
|
+
vendorDir,
|
|
9276
|
+
capacity,
|
|
9277
|
+
vendorPackageTiers
|
|
9278
|
+
}) {
|
|
9279
|
+
let remainingCapacity = capacity;
|
|
9280
|
+
for (const tier of vendorPackageTiers) {
|
|
9281
|
+
if (remainingCapacity <= 0)
|
|
9282
|
+
break;
|
|
9283
|
+
if (tier && tier.length === 0)
|
|
9284
|
+
continue;
|
|
9285
|
+
const bytecodeInfo = await depExternalizer.collectBytecodeFiles({
|
|
9286
|
+
vendorDirName: vendorDir,
|
|
9287
|
+
includePackages: tier
|
|
9288
|
+
});
|
|
9289
|
+
remainingCapacity = await addVendorBytecodeWithinCapacity({
|
|
9290
|
+
files,
|
|
9291
|
+
depExternalizer,
|
|
9292
|
+
vendorDir,
|
|
9293
|
+
bytecodeInfo,
|
|
9294
|
+
capacity: remainingCapacity
|
|
9295
|
+
});
|
|
9296
|
+
}
|
|
9297
|
+
return remainingCapacity;
|
|
9298
|
+
}
|
|
9299
|
+
async function addCollectedVendorBytecode({
|
|
9300
|
+
files,
|
|
9301
|
+
capacity,
|
|
9302
|
+
collect
|
|
9303
|
+
}) {
|
|
9304
|
+
if (capacity <= 0)
|
|
9305
|
+
return capacity;
|
|
9306
|
+
const info = await collect(void 0);
|
|
9307
|
+
if (!info || info.totalSize <= 0)
|
|
9308
|
+
return capacity;
|
|
9309
|
+
if (info.totalSize <= capacity) {
|
|
9310
|
+
addFiles(files, info.files);
|
|
9311
|
+
return capacity - info.totalSize;
|
|
9312
|
+
}
|
|
9313
|
+
const selected = lambdaKnapsack(info.perItemSizes, capacity);
|
|
9314
|
+
if (selected.length === 0)
|
|
9315
|
+
return capacity;
|
|
9316
|
+
const selectedInfo = await collect(selected);
|
|
9317
|
+
addFiles(files, selectedInfo.files);
|
|
9318
|
+
return capacity - selectedInfo.totalSize;
|
|
9319
|
+
}
|
|
8943
9320
|
async function runFrameworkHook(framework, ctx) {
|
|
8944
9321
|
const hook = framework ? frameworkHooks[framework] : void 0;
|
|
8945
9322
|
return hook?.(ctx);
|
|
@@ -8953,13 +9330,13 @@ var frameworkHooks = {
|
|
|
8953
9330
|
}) => {
|
|
8954
9331
|
let baseDir = detected?.baseDir;
|
|
8955
9332
|
if (baseDir === void 0) {
|
|
8956
|
-
if (!
|
|
8957
|
-
(0,
|
|
9333
|
+
if (!import_fs17.default.existsSync((0, import_path17.join)(workPath, "manage.py"))) {
|
|
9334
|
+
(0, import_build_utils20.debug)("Django hook: no manage.py detected, skipping");
|
|
8958
9335
|
return;
|
|
8959
9336
|
}
|
|
8960
9337
|
baseDir = "";
|
|
8961
9338
|
}
|
|
8962
|
-
const djangoPath = (0,
|
|
9339
|
+
const djangoPath = (0, import_path17.join)(workPath, baseDir);
|
|
8963
9340
|
let settingsResult;
|
|
8964
9341
|
try {
|
|
8965
9342
|
settingsResult = await getDjangoSettings(djangoPath, pythonEnv);
|
|
@@ -8971,13 +9348,13 @@ Hint: activate a venv or run with \`uv run vercel dev\``;
|
|
|
8971
9348
|
} else {
|
|
8972
9349
|
detail = err?.stderr || err?.message || String(err);
|
|
8973
9350
|
}
|
|
8974
|
-
throw new
|
|
9351
|
+
throw new import_build_utils20.NowBuildError({
|
|
8975
9352
|
code: "DJANGO_SETTINGS_FAILED",
|
|
8976
9353
|
message: `Failed to read Django application settings from ${djangoPath}/manage.py:
|
|
8977
9354
|
${detail}`
|
|
8978
9355
|
});
|
|
8979
9356
|
}
|
|
8980
|
-
(0,
|
|
9357
|
+
(0, import_build_utils20.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
|
|
8981
9358
|
const { djangoSettings, settingsModule, djangoVersion } = settingsResult;
|
|
8982
9359
|
if (djangoVersion) {
|
|
8983
9360
|
console.log(`Django ${djangoVersion.join(".")} detected`);
|
|
@@ -8989,7 +9366,7 @@ ${detail}`
|
|
|
8989
9366
|
const variableName = parts.at(-1);
|
|
8990
9367
|
const rel = `${parts.slice(0, -1).join("/")}.py`;
|
|
8991
9368
|
const ep = baseDir ? `${baseDir}/${rel}` : rel;
|
|
8992
|
-
(0,
|
|
9369
|
+
(0, import_build_utils20.debug)(`Django hook: ASGI entrypoint: ${ep} (variable: ${variableName})`);
|
|
8993
9370
|
resolvedEntrypoint = { entrypoint: ep, variableName };
|
|
8994
9371
|
} else {
|
|
8995
9372
|
const wsgiApp = djangoSettings["WSGI_APPLICATION"];
|
|
@@ -8998,7 +9375,7 @@ ${detail}`
|
|
|
8998
9375
|
const variableName = parts.at(-1);
|
|
8999
9376
|
const rel = `${parts.slice(0, -1).join("/")}.py`;
|
|
9000
9377
|
const ep = baseDir ? `${baseDir}/${rel}` : rel;
|
|
9001
|
-
(0,
|
|
9378
|
+
(0, import_build_utils20.debug)(
|
|
9002
9379
|
`Django hook: WSGI entrypoint: ${ep} (variable: ${variableName})`
|
|
9003
9380
|
);
|
|
9004
9381
|
resolvedEntrypoint = { entrypoint: ep, variableName };
|
|
@@ -9006,7 +9383,7 @@ ${detail}`
|
|
|
9006
9383
|
}
|
|
9007
9384
|
let djangoStatic = null;
|
|
9008
9385
|
if (workPath && venvPath) {
|
|
9009
|
-
const outputStaticDir = (0,
|
|
9386
|
+
const outputStaticDir = (0, import_path17.join)(workPath, ".vercel", "output", "static");
|
|
9010
9387
|
djangoStatic = await runDjangoCollectStatic(
|
|
9011
9388
|
venvPath,
|
|
9012
9389
|
workPath,
|
|
@@ -9021,7 +9398,7 @@ ${detail}`
|
|
|
9021
9398
|
return {
|
|
9022
9399
|
entrypoint: resolvedEntrypoint,
|
|
9023
9400
|
djangoStatic,
|
|
9024
|
-
extraPythonPath: baseDir ? (0,
|
|
9401
|
+
extraPythonPath: baseDir ? (0, import_path17.join)(workPath, baseDir) : void 0
|
|
9025
9402
|
};
|
|
9026
9403
|
}
|
|
9027
9404
|
};
|
|
@@ -9080,23 +9457,23 @@ async function downloadFilesInWorkPath({
|
|
|
9080
9457
|
files,
|
|
9081
9458
|
meta = {}
|
|
9082
9459
|
}) {
|
|
9083
|
-
(0,
|
|
9084
|
-
let downloadedFiles = await (0,
|
|
9460
|
+
(0, import_build_utils20.debug)("Downloading user files...");
|
|
9461
|
+
let downloadedFiles = await (0, import_build_utils20.download)(files, workPath, meta);
|
|
9085
9462
|
if (meta.isDev && entrypoint) {
|
|
9086
9463
|
const normalizedEntrypoint = entrypoint.endsWith(".py") ? entrypoint : `${entrypoint}.py`;
|
|
9087
9464
|
if (!hasProp(downloadedFiles, entrypoint) && !hasProp(downloadedFiles, normalizedEntrypoint)) {
|
|
9088
|
-
throw new
|
|
9465
|
+
throw new import_build_utils20.NowBuildError({
|
|
9089
9466
|
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
9090
9467
|
message: `Configured Python entrypoint "${normalizedEntrypoint}" was not found.`,
|
|
9091
9468
|
link: PYTHON_ENTRYPOINT_DOCS_URL2,
|
|
9092
9469
|
action: "Learn More"
|
|
9093
9470
|
});
|
|
9094
9471
|
}
|
|
9095
|
-
const { devCacheDir = (0,
|
|
9096
|
-
const cacheKey = (0,
|
|
9097
|
-
const destCache = (0,
|
|
9098
|
-
await (0,
|
|
9099
|
-
downloadedFiles = await (0,
|
|
9472
|
+
const { devCacheDir = (0, import_path17.join)(workPath, ".now", "cache") } = meta;
|
|
9473
|
+
const cacheKey = (0, import_path17.basename)(entrypoint).replace(/\./g, "_");
|
|
9474
|
+
const destCache = (0, import_path17.join)(devCacheDir, cacheKey);
|
|
9475
|
+
await (0, import_build_utils20.download)(downloadedFiles, destCache);
|
|
9476
|
+
downloadedFiles = await (0, import_build_utils20.glob)("**", destCache);
|
|
9100
9477
|
workPath = destCache;
|
|
9101
9478
|
}
|
|
9102
9479
|
return workPath;
|
|
@@ -9132,7 +9509,7 @@ async function getPythonLambdaOptions({
|
|
|
9132
9509
|
sources.add(entrypoint.slice(0, -".py".length));
|
|
9133
9510
|
}
|
|
9134
9511
|
for (const sourceFile of sources) {
|
|
9135
|
-
const lambdaOptions = await (0,
|
|
9512
|
+
const lambdaOptions = await (0, import_build_utils20.getLambdaOptionsFromFunction)({
|
|
9136
9513
|
sourceFile,
|
|
9137
9514
|
config
|
|
9138
9515
|
});
|
|
@@ -9152,11 +9529,11 @@ async function installInjectedPackage({
|
|
|
9152
9529
|
projectDir,
|
|
9153
9530
|
pipPlatformArgs
|
|
9154
9531
|
}) {
|
|
9155
|
-
const localDir = (0,
|
|
9156
|
-
const isLocalDev =
|
|
9532
|
+
const localDir = (0, import_path17.join)(__dirname, "..", "..", "..", "python", name);
|
|
9533
|
+
const isLocalDev = import_fs17.default.existsSync((0, import_path17.join)(localDir, "pyproject.toml"));
|
|
9157
9534
|
const dep = envOverride || (isLocalDev ? localDir : pinned);
|
|
9158
9535
|
const noExclude = ["--exclude-newer-package", `${name}=false`];
|
|
9159
|
-
(0,
|
|
9536
|
+
(0, import_build_utils20.debug)(`Installing ${dep}`);
|
|
9160
9537
|
await uv.pip({
|
|
9161
9538
|
venvPath,
|
|
9162
9539
|
projectDir,
|
|
@@ -9182,28 +9559,37 @@ var build = async ({
|
|
|
9182
9559
|
registerPreDeploy
|
|
9183
9560
|
}) => {
|
|
9184
9561
|
let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
|
|
9185
|
-
const
|
|
9562
|
+
const isPyprojectEntrypoint = entrypoint !== void 0 && (0, import_path17.basename)(entrypoint) === "pyproject.toml";
|
|
9563
|
+
if (isPyprojectEntrypoint && entrypoint !== "pyproject.toml") {
|
|
9564
|
+
throw new import_build_utils20.NowBuildError({
|
|
9565
|
+
code: "PYTHON_INVALID_PYPROJECT_ENTRYPOINT",
|
|
9566
|
+
message: `A "pyproject.toml" entrypoint must sit at the service root. Set the service "root" to "${(0, import_path17.dirname)(entrypoint)}" and use entrypoint "pyproject.toml".`
|
|
9567
|
+
});
|
|
9568
|
+
}
|
|
9569
|
+
const builderSpan = parentSpan ?? new import_build_utils20.Span({ name: "vc.builder" });
|
|
9186
9570
|
const framework = config?.framework;
|
|
9187
9571
|
let shouldInstallVercelWorkers = config?.hasWorkerServices === true;
|
|
9188
9572
|
let subscribers = [];
|
|
9573
|
+
let workflows = [];
|
|
9189
9574
|
let spawnEnv;
|
|
9190
9575
|
let projectInstallCommand;
|
|
9191
9576
|
let hasCustomCommand = false;
|
|
9192
9577
|
const target = getTargetPlatform(meta.isDev ?? false);
|
|
9193
|
-
(0,
|
|
9578
|
+
(0, import_build_utils20.debug)(`workPath: ${workPath}`);
|
|
9194
9579
|
workPath = await downloadFilesInWorkPath({
|
|
9195
9580
|
workPath,
|
|
9196
9581
|
files: originalFiles,
|
|
9197
9582
|
entrypoint,
|
|
9198
9583
|
meta
|
|
9199
9584
|
});
|
|
9200
|
-
if (!service && (0,
|
|
9585
|
+
if (isPyprojectEntrypoint || !service && (0, import_build_utils20.isPythonFramework)(framework)) {
|
|
9201
9586
|
subscribers = await getPyprojectSubscribers(workPath);
|
|
9202
|
-
|
|
9587
|
+
workflows = await getPyprojectWorkflows(workPath);
|
|
9588
|
+
shouldInstallVercelWorkers ||= subscribers.length > 0 || workflows.length > 0;
|
|
9203
9589
|
}
|
|
9204
9590
|
try {
|
|
9205
9591
|
if (meta.isDev) {
|
|
9206
|
-
const setupCfg = (0,
|
|
9592
|
+
const setupCfg = (0, import_path17.join)(workPath, "setup.cfg");
|
|
9207
9593
|
await writeFile(setupCfg, "[install]\nprefix=\n");
|
|
9208
9594
|
}
|
|
9209
9595
|
} catch (err) {
|
|
@@ -9212,23 +9598,36 @@ var build = async ({
|
|
|
9212
9598
|
}
|
|
9213
9599
|
let detected;
|
|
9214
9600
|
const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9601
|
+
if (isPyprojectEntrypoint) {
|
|
9602
|
+
const declared = await getVercelToolsEntrypoint(workPath, repoRootPath);
|
|
9603
|
+
if (declared) {
|
|
9604
|
+
detected = { entrypoint: declared };
|
|
9605
|
+
} else if (subscribers.length === 0 && workflows.length === 0) {
|
|
9606
|
+
throw new import_build_utils20.NowBuildError({
|
|
9607
|
+
code: "PYTHON_PYPROJECT_NOTHING_TO_BUILD",
|
|
9608
|
+
message: 'Entrypoint "pyproject.toml" declares nothing to build. Set "tool.vercel.entrypoint" for a web app and/or declare "[[tool.vercel.subscribers]]" or "[[tool.vercel.workflows]]" entries in pyproject.toml.'
|
|
9609
|
+
});
|
|
9610
|
+
}
|
|
9611
|
+
entrypoint = void 0;
|
|
9612
|
+
} else {
|
|
9613
|
+
detected = await detectPythonEntrypoint(
|
|
9614
|
+
config.framework,
|
|
9615
|
+
workPath,
|
|
9616
|
+
entrypoint ? {
|
|
9617
|
+
filePath: entrypoint,
|
|
9618
|
+
// For schedule-triggered jobs, the WSGI variable is always 'app' (created dynamically).
|
|
9619
|
+
// For other services, handlerFunction is used as the entrypoint variable name.
|
|
9620
|
+
varName: service && (0, import_build_utils20.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
|
|
9621
|
+
} : void 0,
|
|
9622
|
+
service,
|
|
9623
|
+
repoRootPath
|
|
9624
|
+
) ?? void 0;
|
|
9625
|
+
}
|
|
9227
9626
|
if (detected?.error && detected?.baseDir === void 0) {
|
|
9228
9627
|
throw detected?.error;
|
|
9229
9628
|
}
|
|
9230
|
-
const entryDirectory = detected?.baseDir ?? (entrypoint ? (0,
|
|
9231
|
-
const entrypointAbsDir = (0,
|
|
9629
|
+
const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path17.dirname)(entrypoint) : ".");
|
|
9630
|
+
const entrypointAbsDir = (0, import_path17.join)(workPath, entryDirectory);
|
|
9232
9631
|
const rootDir = repoRootPath ?? workPath;
|
|
9233
9632
|
const pythonPackage = await builderSpan.child("vc.builder.python.discover").trace(
|
|
9234
9633
|
() => discoverPackage({
|
|
@@ -9269,12 +9668,12 @@ var build = async ({
|
|
|
9269
9668
|
}
|
|
9270
9669
|
const uvVersion = checkUvBinaryVersion(uv.getPath());
|
|
9271
9670
|
console.log(`Using ${uvVersion}`);
|
|
9272
|
-
const venvPath = service?.name ? (0,
|
|
9273
|
-
const hasCachedVenv =
|
|
9274
|
-
const hasCachedUv =
|
|
9671
|
+
const venvPath = service?.name ? (0, import_path17.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path17.join)(workPath, ".vercel", "python", ".venv");
|
|
9672
|
+
const hasCachedVenv = import_fs17.default.existsSync((0, import_path17.join)(venvPath, "pyvenv.cfg"));
|
|
9673
|
+
const hasCachedUv = import_fs17.default.existsSync(uvCacheDir);
|
|
9275
9674
|
const restoredCache = hasCachedVenv && hasCachedUv ? "both" : hasCachedVenv ? "venv" : hasCachedUv ? "uv" : "none";
|
|
9276
9675
|
if (hasCachedVenv || hasCachedUv) {
|
|
9277
|
-
(0,
|
|
9676
|
+
(0, import_build_utils20.debug)(
|
|
9278
9677
|
`Build cache detected: venv=${hasCachedVenv}, uv-cache=${hasCachedUv}`
|
|
9279
9678
|
);
|
|
9280
9679
|
}
|
|
@@ -9286,14 +9685,14 @@ var build = async ({
|
|
|
9286
9685
|
uvCacheDir
|
|
9287
9686
|
});
|
|
9288
9687
|
});
|
|
9289
|
-
if ((0,
|
|
9688
|
+
if ((0, import_build_utils20.isPythonFramework)(framework)) {
|
|
9290
9689
|
const {
|
|
9291
9690
|
cliType,
|
|
9292
9691
|
lockfileVersion,
|
|
9293
9692
|
packageJsonPackageManager,
|
|
9294
9693
|
turboSupportsCorepackHome
|
|
9295
|
-
} = await (0,
|
|
9296
|
-
spawnEnv = (0,
|
|
9694
|
+
} = await (0, import_build_utils20.scanParentDirs)(workPath, true);
|
|
9695
|
+
spawnEnv = (0, import_build_utils20.getEnvForPackageManager)({
|
|
9297
9696
|
cliType,
|
|
9298
9697
|
lockfileVersion,
|
|
9299
9698
|
packageJsonPackageManager,
|
|
@@ -9318,13 +9717,13 @@ var build = async ({
|
|
|
9318
9717
|
let uvLockPath = null;
|
|
9319
9718
|
let uvProjectDir = null;
|
|
9320
9719
|
let projectName;
|
|
9321
|
-
await builderSpan.child(
|
|
9720
|
+
await builderSpan.child(import_build_utils20.BUILDER_INSTALLER_STEP, {
|
|
9322
9721
|
installCommand: projectInstallCommand || void 0,
|
|
9323
9722
|
runtime: "python",
|
|
9324
9723
|
"python.cache.restored": restoredCache
|
|
9325
9724
|
}).trace(async () => {
|
|
9326
9725
|
if (projectInstallCommand) {
|
|
9327
|
-
await
|
|
9726
|
+
await import_fs17.default.promises.rm(venvPath, { recursive: true, force: true });
|
|
9328
9727
|
await ensureVenv({
|
|
9329
9728
|
pythonVersion,
|
|
9330
9729
|
venvPath,
|
|
@@ -9335,7 +9734,7 @@ var build = async ({
|
|
|
9335
9734
|
console.log(
|
|
9336
9735
|
`Running "install" command: \`${projectInstallCommand}\`...`
|
|
9337
9736
|
);
|
|
9338
|
-
await (0,
|
|
9737
|
+
await (0, import_build_utils20.execCommand)(projectInstallCommand, {
|
|
9339
9738
|
env: pythonEnv,
|
|
9340
9739
|
cwd: workPath
|
|
9341
9740
|
});
|
|
@@ -9356,7 +9755,7 @@ var build = async ({
|
|
|
9356
9755
|
}
|
|
9357
9756
|
if (!assumeDepsInstalled) {
|
|
9358
9757
|
const lockCacheKey = service?.name ? `uv.lock.${service.name}` : "uv.lock";
|
|
9359
|
-
const cachedLockPath = (0,
|
|
9758
|
+
const cachedLockPath = (0, import_path17.join)(uvCacheDir, lockCacheKey);
|
|
9360
9759
|
const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
|
|
9361
9760
|
workPath,
|
|
9362
9761
|
rootDir,
|
|
@@ -9377,21 +9776,21 @@ var build = async ({
|
|
|
9377
9776
|
locked: !lockFileProvidedByUser,
|
|
9378
9777
|
pythonPlatform: target.uvPlatform
|
|
9379
9778
|
});
|
|
9380
|
-
if (lockPath &&
|
|
9381
|
-
await
|
|
9382
|
-
await
|
|
9779
|
+
if (lockPath && import_fs17.default.existsSync(lockPath)) {
|
|
9780
|
+
await import_fs17.default.promises.mkdir(uvCacheDir, { recursive: true });
|
|
9781
|
+
await import_fs17.default.promises.copyFile(lockPath, cachedLockPath);
|
|
9383
9782
|
}
|
|
9384
9783
|
}
|
|
9385
9784
|
});
|
|
9386
|
-
if ((0,
|
|
9785
|
+
if ((0, import_build_utils20.isPythonFramework)(framework)) {
|
|
9387
9786
|
const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
|
|
9388
9787
|
config?.buildCommand;
|
|
9389
|
-
await builderSpan.child(
|
|
9788
|
+
await builderSpan.child(import_build_utils20.BUILDER_COMPILE_STEP, {
|
|
9390
9789
|
buildCommand: projectBuildCommand || void 0
|
|
9391
9790
|
}).trace(async () => {
|
|
9392
9791
|
if (projectBuildCommand) {
|
|
9393
9792
|
console.log(`Running "${projectBuildCommand}"`);
|
|
9394
|
-
await (0,
|
|
9793
|
+
await (0, import_build_utils20.execCommand)(projectBuildCommand, {
|
|
9395
9794
|
env: pythonEnv,
|
|
9396
9795
|
cwd: workPath
|
|
9397
9796
|
});
|
|
@@ -9411,13 +9810,14 @@ var build = async ({
|
|
|
9411
9810
|
entrypoint,
|
|
9412
9811
|
detected
|
|
9413
9812
|
});
|
|
9414
|
-
const resolved = hookResult?.entrypoint ?? detected?.entrypoint;
|
|
9813
|
+
const resolved = isPyprojectEntrypoint ? detected?.entrypoint : hookResult?.entrypoint ?? detected?.entrypoint;
|
|
9415
9814
|
if (!resolved && detected?.error) {
|
|
9416
9815
|
throw detected?.error;
|
|
9417
9816
|
}
|
|
9418
9817
|
entrypoint = resolved?.entrypoint;
|
|
9419
|
-
|
|
9420
|
-
|
|
9818
|
+
const isWorkersOnly = !entrypoint && isPyprojectEntrypoint && (subscribers.length > 0 || workflows.length > 0);
|
|
9819
|
+
if (!entrypoint && !isWorkersOnly) {
|
|
9820
|
+
throw new import_build_utils20.NowBuildError({
|
|
9421
9821
|
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
9422
9822
|
message: "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
9423
9823
|
});
|
|
@@ -9430,7 +9830,7 @@ var build = async ({
|
|
|
9430
9830
|
envOverride: baseEnv.VERCEL_RUNTIME_PYTHON,
|
|
9431
9831
|
uv,
|
|
9432
9832
|
venvPath,
|
|
9433
|
-
projectDir: (0,
|
|
9833
|
+
projectDir: (0, import_path17.join)(workPath, entryDirectory),
|
|
9434
9834
|
pipPlatformArgs
|
|
9435
9835
|
});
|
|
9436
9836
|
if (shouldInstallVercelWorkers) {
|
|
@@ -9440,7 +9840,7 @@ var build = async ({
|
|
|
9440
9840
|
envOverride: baseEnv.VERCEL_WORKERS_PYTHON,
|
|
9441
9841
|
uv,
|
|
9442
9842
|
venvPath,
|
|
9443
|
-
projectDir: (0,
|
|
9843
|
+
projectDir: (0, import_path17.join)(workPath, entryDirectory),
|
|
9444
9844
|
pipPlatformArgs
|
|
9445
9845
|
});
|
|
9446
9846
|
}
|
|
@@ -9453,57 +9853,61 @@ var build = async ({
|
|
|
9453
9853
|
const capturedEnv = { ...pythonEnv };
|
|
9454
9854
|
const capturedCwd = workPath;
|
|
9455
9855
|
registerPreDeploy(async () => {
|
|
9456
|
-
await builderSpan.child(
|
|
9856
|
+
await builderSpan.child(import_build_utils20.BUILDER_PRE_DEPLOY_STEP, {
|
|
9457
9857
|
preDeployCommand
|
|
9458
9858
|
}).trace(async () => {
|
|
9459
9859
|
console.log(`Running pre-deploy command: \`${preDeployCommand}\``);
|
|
9460
|
-
await (0,
|
|
9860
|
+
await (0, import_build_utils20.execCommand)(preDeployCommand, {
|
|
9461
9861
|
env: capturedEnv,
|
|
9462
9862
|
cwd: capturedCwd
|
|
9463
9863
|
});
|
|
9464
9864
|
});
|
|
9465
9865
|
});
|
|
9466
9866
|
}
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
const
|
|
9473
|
-
if (
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9867
|
+
const vendorDir = resolveVendorDir();
|
|
9868
|
+
let crons;
|
|
9869
|
+
let runtimeTrampoline;
|
|
9870
|
+
if (entrypoint) {
|
|
9871
|
+
(0, import_build_utils20.debug)("Entrypoint is", entrypoint);
|
|
9872
|
+
const moduleName = entrypointToModule(entrypoint);
|
|
9873
|
+
if (handlerFunction) {
|
|
9874
|
+
const entrypointPath = (0, import_path17.join)(workPath, entrypoint);
|
|
9875
|
+
const source = await import_fs17.default.promises.readFile(entrypointPath, "utf-8");
|
|
9876
|
+
const found = await (0, import_python_analysis9.containsTopLevelCallable)(source, handlerFunction);
|
|
9877
|
+
if (!found) {
|
|
9878
|
+
throw new import_build_utils20.NowBuildError({
|
|
9879
|
+
code: "PYTHON_HANDLER_NOT_FOUND",
|
|
9880
|
+
message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
|
|
9881
|
+
});
|
|
9882
|
+
}
|
|
9478
9883
|
}
|
|
9884
|
+
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
9885
|
+
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
9886
|
+
(0, import_build_utils20.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
9887
|
+
crons = await getServiceCrons({
|
|
9888
|
+
service,
|
|
9889
|
+
entrypoint,
|
|
9890
|
+
rawEntrypoint,
|
|
9891
|
+
handlerFunction,
|
|
9892
|
+
pythonBin: getVenvPythonBin(venvPath),
|
|
9893
|
+
env: pythonEnv,
|
|
9894
|
+
workPath
|
|
9895
|
+
});
|
|
9896
|
+
const extraTrampolineEnv = [];
|
|
9897
|
+
if (crons?.length) {
|
|
9898
|
+
const json = JSON.stringify(buildCronRouteTable(crons));
|
|
9899
|
+
(0, import_assert.default)(!json.includes("\\"), `backslash in cron route table: ${json}`);
|
|
9900
|
+
extraTrampolineEnv.push(`"__VC_CRON_ROUTES": '${json}'`);
|
|
9901
|
+
}
|
|
9902
|
+
const variableName = resolved?.variableName ?? "";
|
|
9903
|
+
runtimeTrampoline = createRuntimeTrampoline({
|
|
9904
|
+
moduleName,
|
|
9905
|
+
entrypoint: entrypointWithSuffix,
|
|
9906
|
+
vendorDir,
|
|
9907
|
+
variableName,
|
|
9908
|
+
extraEnv: extraTrampolineEnv
|
|
9909
|
+
});
|
|
9479
9910
|
}
|
|
9480
|
-
const vendorDir = resolveVendorDir();
|
|
9481
|
-
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
9482
|
-
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
9483
|
-
(0, import_build_utils19.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
9484
|
-
const crons = await getServiceCrons({
|
|
9485
|
-
service,
|
|
9486
|
-
entrypoint,
|
|
9487
|
-
rawEntrypoint,
|
|
9488
|
-
handlerFunction,
|
|
9489
|
-
pythonBin: getVenvPythonBin(venvPath),
|
|
9490
|
-
env: pythonEnv,
|
|
9491
|
-
workPath
|
|
9492
|
-
});
|
|
9493
|
-
const extraTrampolineEnv = [];
|
|
9494
|
-
if (crons?.length) {
|
|
9495
|
-
const json = JSON.stringify(buildCronRouteTable(crons));
|
|
9496
|
-
(0, import_assert.default)(!json.includes("\\"), `backslash in cron route table: ${json}`);
|
|
9497
|
-
extraTrampolineEnv.push(`"__VC_CRON_ROUTES": '${json}'`);
|
|
9498
|
-
}
|
|
9499
|
-
const variableName = resolved?.variableName ?? "";
|
|
9500
|
-
const runtimeTrampoline = createRuntimeTrampoline({
|
|
9501
|
-
moduleName,
|
|
9502
|
-
entrypoint: entrypointWithSuffix,
|
|
9503
|
-
vendorDir,
|
|
9504
|
-
variableName,
|
|
9505
|
-
extraEnv: extraTrampolineEnv
|
|
9506
|
-
});
|
|
9507
9911
|
const compileAllEnabled = shouldCompileAll({
|
|
9508
9912
|
isDev: meta.isDev,
|
|
9509
9913
|
hasCustomCommand,
|
|
@@ -9540,16 +9944,16 @@ var build = async ({
|
|
|
9540
9944
|
cwd: workPath,
|
|
9541
9945
|
ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
|
|
9542
9946
|
};
|
|
9543
|
-
const files = await (0,
|
|
9947
|
+
const files = await (0, import_build_utils20.glob)("**", globOptions);
|
|
9544
9948
|
if (djangoStatic?.manifestRelPath) {
|
|
9545
|
-
files[djangoStatic.manifestRelPath] = new
|
|
9546
|
-
fsPath: (0,
|
|
9949
|
+
files[djangoStatic.manifestRelPath] = new import_build_utils20.FileFsRef({
|
|
9950
|
+
fsPath: (0, import_path17.join)(workPath, djangoStatic.manifestRelPath)
|
|
9547
9951
|
});
|
|
9548
9952
|
}
|
|
9549
9953
|
const handlerPyFilename = "vc__handler__python";
|
|
9550
9954
|
if (config.framework === "fasthtml") {
|
|
9551
9955
|
const { SESSKEY = "" } = process.env;
|
|
9552
|
-
files[".sesskey"] = new
|
|
9956
|
+
files[".sesskey"] = new import_build_utils20.FileBlob({ data: `"${SESSKEY}"` });
|
|
9553
9957
|
}
|
|
9554
9958
|
const depExternalizer = new PythonDependencyExternalizer({
|
|
9555
9959
|
venvPath,
|
|
@@ -9578,10 +9982,10 @@ var build = async ({
|
|
|
9578
9982
|
});
|
|
9579
9983
|
}
|
|
9580
9984
|
});
|
|
9581
|
-
const runCompileAllAndFillBytecode = async (capacityBytes) => {
|
|
9985
|
+
const runCompileAllAndFillBytecode = async (capacityBytes, vendorPackageTiers) => {
|
|
9582
9986
|
try {
|
|
9583
9987
|
await builderSpan.child("vc.builder.python.compileall").trace(async (compileSpan) => {
|
|
9584
|
-
const sitePackageDirs = (await getVenvSitePackagesDirs(venvPath)).filter((d) =>
|
|
9988
|
+
const sitePackageDirs = (await getVenvSitePackagesDirs(venvPath)).filter((d) => import_fs17.default.existsSync(d));
|
|
9585
9989
|
const pythonBin = getVenvPythonBin(venvPath);
|
|
9586
9990
|
console.log("Compiling Python bytecode...");
|
|
9587
9991
|
await runCompileAll({
|
|
@@ -9617,37 +10021,133 @@ var build = async ({
|
|
|
9617
10021
|
remainingCapacity
|
|
9618
10022
|
);
|
|
9619
10023
|
}
|
|
9620
|
-
|
|
9621
|
-
{
|
|
9622
|
-
vendorDirName: vendorDir
|
|
9623
|
-
}
|
|
9624
|
-
);
|
|
9625
|
-
await addVendorBytecodeWithinCapacity({
|
|
10024
|
+
await addVendorBytecodeInTiers({
|
|
9626
10025
|
files,
|
|
9627
10026
|
depExternalizer,
|
|
9628
10027
|
vendorDir,
|
|
9629
|
-
|
|
9630
|
-
|
|
10028
|
+
capacity: remainingCapacity,
|
|
10029
|
+
vendorPackageTiers: vendorPackageTiers ?? [void 0]
|
|
9631
10030
|
});
|
|
9632
10031
|
} catch (err) {
|
|
9633
10032
|
console.log(
|
|
9634
10033
|
"Bytecode precompilation failed; continuing without precompiled bytecode."
|
|
9635
10034
|
);
|
|
9636
|
-
(0,
|
|
10035
|
+
(0, import_build_utils20.debug)(`bytecode precompilation error details: ${err}`);
|
|
10036
|
+
}
|
|
10037
|
+
};
|
|
10038
|
+
const runPrefixCompileAndFill = async (bundleResult) => {
|
|
10039
|
+
const pyMajor = pythonVersion.major;
|
|
10040
|
+
const pyMinor = pythonVersion.minor;
|
|
10041
|
+
if (pyMajor == null || pyMinor == null)
|
|
10042
|
+
return;
|
|
10043
|
+
try {
|
|
10044
|
+
const currentSize = await calculateBundleSize(files);
|
|
10045
|
+
let remainingCapacity = BYTECODE_FILL_CEILING_BYTES - currentSize;
|
|
10046
|
+
if (remainingCapacity <= 0) {
|
|
10047
|
+
(0, import_build_utils20.debug)(
|
|
10048
|
+
`skipping bytecode precompilation: no zip capacity remaining (bundle is ${(currentSize / (1024 * 1024)).toFixed(2)} MB)`
|
|
10049
|
+
);
|
|
10050
|
+
return;
|
|
10051
|
+
}
|
|
10052
|
+
const stagingDir = (0, import_path17.join)(workPath, ".vercel", "python", "pycache");
|
|
10053
|
+
await import_fs17.default.promises.rm(stagingDir, { recursive: true, force: true });
|
|
10054
|
+
await import_fs17.default.promises.mkdir(stagingDir, { recursive: true });
|
|
10055
|
+
await builderSpan.child("vc.builder.python.compileall").trace(async (compileSpan) => {
|
|
10056
|
+
const sitePackageDirs = (await getVenvSitePackagesDirs(venvPath)).filter((d) => import_fs17.default.existsSync(d));
|
|
10057
|
+
const pythonBin = getVenvPythonBin(venvPath);
|
|
10058
|
+
console.log("Compiling Python bytecode...");
|
|
10059
|
+
await runCompileAll({
|
|
10060
|
+
pythonBin,
|
|
10061
|
+
filesOrDirectories: [workPath],
|
|
10062
|
+
env: pythonEnv,
|
|
10063
|
+
excludeRegex: getCompileAllAppExcludeRegex(workPath),
|
|
10064
|
+
pycachePrefix: stagingDir
|
|
10065
|
+
});
|
|
10066
|
+
await runCompileAll({
|
|
10067
|
+
pythonBin,
|
|
10068
|
+
filesOrDirectories: sitePackageDirs,
|
|
10069
|
+
env: pythonEnv,
|
|
10070
|
+
pycachePrefix: stagingDir
|
|
10071
|
+
});
|
|
10072
|
+
compileSpan.setAttributes({
|
|
10073
|
+
"python.compileall.enabled": "true",
|
|
10074
|
+
"python.compileall.mode": "pycache-prefix",
|
|
10075
|
+
"python.compileall.sitePackageDirectoryCount": String(
|
|
10076
|
+
sitePackageDirs.length
|
|
10077
|
+
)
|
|
10078
|
+
});
|
|
10079
|
+
});
|
|
10080
|
+
const beforeCount = Object.keys(files).length;
|
|
10081
|
+
const appInfo = await collectAppPrefixBytecodeFiles({
|
|
10082
|
+
stagingDir,
|
|
10083
|
+
workPath,
|
|
10084
|
+
files,
|
|
10085
|
+
runtimeTaskRoot: "/var/task",
|
|
10086
|
+
pythonMajor: pyMajor,
|
|
10087
|
+
pythonMinor: pyMinor
|
|
10088
|
+
});
|
|
10089
|
+
remainingCapacity = addBytecodeWithinCapacity(
|
|
10090
|
+
files,
|
|
10091
|
+
appInfo,
|
|
10092
|
+
remainingCapacity
|
|
10093
|
+
);
|
|
10094
|
+
const alwaysBundled = bundleResult.alwaysBundledPackages ?? [];
|
|
10095
|
+
remainingCapacity = await addCollectedVendorBytecode({
|
|
10096
|
+
files,
|
|
10097
|
+
capacity: remainingCapacity,
|
|
10098
|
+
collect: (include) => depExternalizer.collectPrefixBytecodeFiles({
|
|
10099
|
+
stagingDir,
|
|
10100
|
+
runtimeRoot: `/var/task/${vendorDir}`,
|
|
10101
|
+
includePackages: include ?? alwaysBundled
|
|
10102
|
+
})
|
|
10103
|
+
});
|
|
10104
|
+
const externalized = bundleResult.externalizedPublicPackages ?? [];
|
|
10105
|
+
await addCollectedVendorBytecode({
|
|
10106
|
+
files,
|
|
10107
|
+
capacity: remainingCapacity,
|
|
10108
|
+
collect: (include) => depExternalizer.collectPrefixBytecodeFiles({
|
|
10109
|
+
stagingDir,
|
|
10110
|
+
runtimeRoot: `${RUNTIME_DEPS_DIR}/lib/python${pyMajor}.${pyMinor}/site-packages`,
|
|
10111
|
+
includePackages: include ?? externalized
|
|
10112
|
+
})
|
|
10113
|
+
});
|
|
10114
|
+
if (Object.keys(files).length > beforeCount) {
|
|
10115
|
+
lambdaEnv.PYTHONPYCACHEPREFIX = RUNTIME_PYCACHE_PREFIX;
|
|
10116
|
+
}
|
|
10117
|
+
} catch (err) {
|
|
10118
|
+
console.log(
|
|
10119
|
+
"Bytecode precompilation failed; continuing without precompiled bytecode."
|
|
10120
|
+
);
|
|
10121
|
+
(0, import_build_utils20.debug)(`bytecode precompilation error details: ${err}`);
|
|
9637
10122
|
}
|
|
9638
10123
|
};
|
|
9639
10124
|
const announceLargeFunction = () => console.log(
|
|
9640
|
-
`Function "${entrypoint}" exceeds the standard size limit; enabling large functions (beta).`
|
|
10125
|
+
`Function "${entrypoint ?? rawEntrypoint}" exceeds the standard size limit; enabling large functions (beta).`
|
|
9641
10126
|
);
|
|
9642
10127
|
if (depAnalysis.runtimeInstallEnabled) {
|
|
9643
|
-
const
|
|
9644
|
-
|
|
10128
|
+
const bytecodeFirst = compileAllEnabled && pythonVersion.major != null && pythonVersion.minor != null;
|
|
10129
|
+
const bundleResult = await depExternalizer.generateBundle(files, {
|
|
10130
|
+
bytecodeFirst
|
|
10131
|
+
});
|
|
10132
|
+
if (bundleResult.fellBackToFullBundle) {
|
|
9645
10133
|
announceLargeFunction();
|
|
9646
10134
|
if (compileAllEnabled) {
|
|
9647
10135
|
await runCompileAllAndFillBytecode(
|
|
9648
10136
|
MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE
|
|
9649
10137
|
);
|
|
9650
10138
|
}
|
|
10139
|
+
} else if (bundleResult.packingMode === "bytecode-first") {
|
|
10140
|
+
await runPrefixCompileAndFill(bundleResult);
|
|
10141
|
+
} else if (compileAllEnabled) {
|
|
10142
|
+
const currentSize = await calculateBundleSize(files);
|
|
10143
|
+
const capacity = BYTECODE_FILL_CEILING_BYTES - currentSize;
|
|
10144
|
+
const estimate = await estimateBytecodeSize(files);
|
|
10145
|
+
if (capacity >= BYTECODE_COVERAGE_FLOOR * estimate) {
|
|
10146
|
+
await runCompileAllAndFillBytecode(BYTECODE_FILL_CEILING_BYTES, [
|
|
10147
|
+
bundleResult.alwaysBundledPackages ?? [],
|
|
10148
|
+
bundleResult.bundledPublicPackages ?? []
|
|
10149
|
+
]);
|
|
10150
|
+
}
|
|
9651
10151
|
}
|
|
9652
10152
|
} else {
|
|
9653
10153
|
addFiles(files, depAnalysis.allVendorFiles);
|
|
@@ -9669,23 +10169,26 @@ var build = async ({
|
|
|
9669
10169
|
}
|
|
9670
10170
|
}
|
|
9671
10171
|
});
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
10172
|
+
let output;
|
|
10173
|
+
if (entrypoint && runtimeTrampoline) {
|
|
10174
|
+
const webFiles = {
|
|
10175
|
+
...files,
|
|
10176
|
+
[`${handlerPyFilename}.py`]: new import_build_utils20.FileBlob({ data: runtimeTrampoline })
|
|
10177
|
+
};
|
|
10178
|
+
const lambdaOptions = await getPythonLambdaOptions({
|
|
10179
|
+
config,
|
|
10180
|
+
entrypoint
|
|
10181
|
+
});
|
|
10182
|
+
output = new import_build_utils20.Lambda({
|
|
10183
|
+
files: webFiles,
|
|
10184
|
+
handler: `${handlerPyFilename}.vc_handler`,
|
|
10185
|
+
runtime: pythonVersion.runtime,
|
|
10186
|
+
...lambdaOptions,
|
|
10187
|
+
architecture: target.architecture,
|
|
10188
|
+
environment: lambdaEnv,
|
|
10189
|
+
supportsResponseStreaming: true
|
|
10190
|
+
});
|
|
10191
|
+
}
|
|
9689
10192
|
const subscriberLambdas = {};
|
|
9690
10193
|
for (const subscriber of subscribers) {
|
|
9691
10194
|
const outputPath = getSubscriberOutputPath(subscriber.name);
|
|
@@ -9698,10 +10201,10 @@ var build = async ({
|
|
|
9698
10201
|
...subscriber.triggerDefaults
|
|
9699
10202
|
})
|
|
9700
10203
|
);
|
|
9701
|
-
subscriberLambdas[outputPath] = new
|
|
10204
|
+
subscriberLambdas[outputPath] = new import_build_utils20.Lambda({
|
|
9702
10205
|
files: {
|
|
9703
10206
|
...files,
|
|
9704
|
-
[`${handlerPyFilename}.py`]: new
|
|
10207
|
+
[`${handlerPyFilename}.py`]: new import_build_utils20.FileBlob({
|
|
9705
10208
|
data: createRuntimeTrampoline({
|
|
9706
10209
|
moduleName: subscriber.moduleName,
|
|
9707
10210
|
entrypoint: subscriber.entrypoint,
|
|
@@ -9723,6 +10226,41 @@ var build = async ({
|
|
|
9723
10226
|
supportsResponseStreaming: true
|
|
9724
10227
|
});
|
|
9725
10228
|
}
|
|
10229
|
+
const workflowLambdas = {};
|
|
10230
|
+
for (const workflow of workflows) {
|
|
10231
|
+
const outputPath = getWorkflowOutputPath(workflow.name);
|
|
10232
|
+
const experimentalTriggers = [
|
|
10233
|
+
{
|
|
10234
|
+
type: "queue/v2beta",
|
|
10235
|
+
topic: WORKFLOW_TOPIC_PATTERN,
|
|
10236
|
+
consumer: getWorkflowConsumerName(workflow.name)
|
|
10237
|
+
}
|
|
10238
|
+
];
|
|
10239
|
+
workflowLambdas[outputPath] = new import_build_utils20.Lambda({
|
|
10240
|
+
files: {
|
|
10241
|
+
...files,
|
|
10242
|
+
[`${handlerPyFilename}.py`]: new import_build_utils20.FileBlob({
|
|
10243
|
+
data: createRuntimeTrampoline({
|
|
10244
|
+
moduleName: workflow.moduleName,
|
|
10245
|
+
entrypoint: workflow.entrypoint,
|
|
10246
|
+
vendorDir,
|
|
10247
|
+
variableName: workflow.variableName
|
|
10248
|
+
})
|
|
10249
|
+
})
|
|
10250
|
+
},
|
|
10251
|
+
handler: `${handlerPyFilename}.vc_handler`,
|
|
10252
|
+
runtime: pythonVersion.runtime,
|
|
10253
|
+
architecture: target.architecture,
|
|
10254
|
+
environment: {
|
|
10255
|
+
...lambdaEnv,
|
|
10256
|
+
VERCEL_HAS_WORKER_SERVICES: "1",
|
|
10257
|
+
// Compatibility marker consumed by the current Python runtime.
|
|
10258
|
+
VERCEL_SERVICE_TYPE: "worker"
|
|
10259
|
+
},
|
|
10260
|
+
experimentalTriggers,
|
|
10261
|
+
supportsResponseStreaming: true
|
|
10262
|
+
});
|
|
10263
|
+
}
|
|
9726
10264
|
if (uvLockPath && !meta.isDev) {
|
|
9727
10265
|
try {
|
|
9728
10266
|
await generateProjectManifest({
|
|
@@ -9731,21 +10269,22 @@ var build = async ({
|
|
|
9731
10269
|
pythonVersion,
|
|
9732
10270
|
uvLockPath,
|
|
9733
10271
|
framework,
|
|
9734
|
-
serviceType: service ? (0,
|
|
10272
|
+
serviceType: service ? (0, import_build_utils20.getReportedServiceType)(service) : void 0
|
|
9735
10273
|
});
|
|
9736
10274
|
} catch (err) {
|
|
9737
|
-
(0,
|
|
10275
|
+
(0, import_build_utils20.debug)(
|
|
9738
10276
|
`Failed to write project manifest: ${err instanceof Error ? err.message : String(err)}`
|
|
9739
10277
|
);
|
|
9740
10278
|
}
|
|
9741
10279
|
}
|
|
9742
|
-
if (!(0,
|
|
10280
|
+
if (!(0, import_build_utils20.isPythonFramework)(framework) && !service?.name && !isPyprojectEntrypoint) {
|
|
10281
|
+
(0, import_assert.default)(output, "web Lambda must exist for non-service builds");
|
|
9743
10282
|
return { resultVersion: 3, result: { output } };
|
|
9744
10283
|
}
|
|
9745
10284
|
const lambdaPath = service?.name && service.type ? `_svc/${service.name}/index` : "index";
|
|
9746
|
-
const staticFiles = djangoStatic?.cdnOutputDir ? await (0,
|
|
10285
|
+
const staticFiles = djangoStatic?.cdnOutputDir ? await (0, import_build_utils20.glob)("**", { cwd: djangoStatic.cdnOutputDir }) : {};
|
|
9747
10286
|
const isNonWebService = service?.name && service.type && service.type !== "web";
|
|
9748
|
-
const routes = isNonWebService ? void 0 : [
|
|
10287
|
+
const routes = isNonWebService || !output ? void 0 : [
|
|
9749
10288
|
{ handle: "filesystem" },
|
|
9750
10289
|
{ src: "/(.*)", dest: `/${lambdaPath}` }
|
|
9751
10290
|
];
|
|
@@ -9753,8 +10292,9 @@ var build = async ({
|
|
|
9753
10292
|
resultVersion: 2,
|
|
9754
10293
|
result: {
|
|
9755
10294
|
output: {
|
|
9756
|
-
[lambdaPath]: output,
|
|
10295
|
+
...output ? { [lambdaPath]: output } : {},
|
|
9757
10296
|
...subscriberLambdas,
|
|
10297
|
+
...workflowLambdas,
|
|
9758
10298
|
...staticFiles
|
|
9759
10299
|
},
|
|
9760
10300
|
...routes ? { routes } : {},
|
|
@@ -9777,14 +10317,14 @@ var prepareCache = async ({
|
|
|
9777
10317
|
}
|
|
9778
10318
|
} catch {
|
|
9779
10319
|
}
|
|
9780
|
-
return (0,
|
|
10320
|
+
return (0, import_build_utils20.glob)("**/.vercel/python/{.venv,services/*/.venv,cache/uv}/**", {
|
|
9781
10321
|
cwd: root,
|
|
9782
10322
|
ignore
|
|
9783
10323
|
});
|
|
9784
10324
|
};
|
|
9785
10325
|
var shouldServe = (opts) => {
|
|
9786
10326
|
const framework = opts.config.framework;
|
|
9787
|
-
if ((0,
|
|
10327
|
+
if ((0, import_build_utils20.isPythonFramework)(framework)) {
|
|
9788
10328
|
const requestPath = opts.requestPath.replace(/\/$/, "");
|
|
9789
10329
|
if (requestPath.startsWith("api") && opts.hasMatched) {
|
|
9790
10330
|
return false;
|
|
@@ -9803,7 +10343,7 @@ var defaultShouldServe = ({
|
|
|
9803
10343
|
if (entrypoint === requestPath && hasProp(files, entrypoint)) {
|
|
9804
10344
|
return true;
|
|
9805
10345
|
}
|
|
9806
|
-
const { dir, name } = (0,
|
|
10346
|
+
const { dir, name } = (0, import_path17.parse)(entrypoint);
|
|
9807
10347
|
if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
|
|
9808
10348
|
return true;
|
|
9809
10349
|
}
|
|
@@ -9814,6 +10354,8 @@ function hasProp(obj, key) {
|
|
|
9814
10354
|
}
|
|
9815
10355
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9816
10356
|
0 && (module.exports = {
|
|
10357
|
+
addCollectedVendorBytecode,
|
|
10358
|
+
addVendorBytecodeInTiers,
|
|
9817
10359
|
build,
|
|
9818
10360
|
defaultShouldServe,
|
|
9819
10361
|
detectEntrypoint,
|