@vercel/python 6.49.0 → 6.51.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 +841 -272
- package/package.json +2 -2
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,7 +5895,10 @@ 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;
|
|
5901
|
+
var LARGE_FUNCTION_FILL_CEILING_BYTES = MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE - BYTECODE_FILL_MARGIN_BYTES;
|
|
5804
5902
|
var BUNDLING_DOCS_LINK = "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled";
|
|
5805
5903
|
var PythonDependencyExternalizer = class {
|
|
5806
5904
|
constructor(options) {
|
|
@@ -5910,7 +6008,7 @@ application into smaller functions.`,
|
|
|
5910
6008
|
* back to bundling everything for Hive and returns `fellBackToFullBundle:
|
|
5911
6009
|
* true` so the caller can apply the same compileall handling.
|
|
5912
6010
|
*/
|
|
5913
|
-
async generateBundle(files) {
|
|
6011
|
+
async generateBundle(files, options = {}) {
|
|
5914
6012
|
if (!this.analyzed) {
|
|
5915
6013
|
throw new Error(
|
|
5916
6014
|
"PythonDependencyExternalizer.analyze() must be called before generateBundle()"
|
|
@@ -6071,7 +6169,20 @@ To fix this, either:
|
|
|
6071
6169
|
([name]) => externalizableSet.has((0, import_python_analysis3.normalizePackageName)(name))
|
|
6072
6170
|
)
|
|
6073
6171
|
);
|
|
6074
|
-
const bundledPublic =
|
|
6172
|
+
const { packingMode, bundledPublic } = planPublicPackagePacking({
|
|
6173
|
+
publicPackageSizes,
|
|
6174
|
+
zipCapacity: remainingCapacity,
|
|
6175
|
+
bytecodeFirst: options.bytecodeFirst ?? false
|
|
6176
|
+
});
|
|
6177
|
+
if (options.bytecodeFirst && packingMode === "knapsack") {
|
|
6178
|
+
(0, import_build_utils7.debug)(
|
|
6179
|
+
`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`
|
|
6180
|
+
);
|
|
6181
|
+
}
|
|
6182
|
+
const bundledPublicSet = new Set(bundledPublic.map(import_python_analysis3.normalizePackageName));
|
|
6183
|
+
const externalizedPublic = externalizablePublic.filter(
|
|
6184
|
+
(name) => !bundledPublicSet.has((0, import_python_analysis3.normalizePackageName)(name))
|
|
6185
|
+
);
|
|
6075
6186
|
const allBundledPackages = [...alwaysBundled, ...bundledPublic];
|
|
6076
6187
|
const selectedVendorFiles = await this.mirrorPackagesIntoVendor({
|
|
6077
6188
|
vendorDirName: this.vendorDir,
|
|
@@ -6143,7 +6254,13 @@ functions.`,
|
|
|
6143
6254
|
action: "Learn More"
|
|
6144
6255
|
});
|
|
6145
6256
|
}
|
|
6146
|
-
return {
|
|
6257
|
+
return {
|
|
6258
|
+
fellBackToFullBundle: false,
|
|
6259
|
+
packingMode,
|
|
6260
|
+
alwaysBundledPackages: alwaysBundled,
|
|
6261
|
+
bundledPublicPackages: bundledPublic,
|
|
6262
|
+
externalizedPublicPackages: externalizedPublic
|
|
6263
|
+
};
|
|
6147
6264
|
}
|
|
6148
6265
|
/**
|
|
6149
6266
|
* Discard any runtime-install artifacts added so far and bundle every
|
|
@@ -6456,6 +6573,92 @@ functions.`,
|
|
|
6456
6573
|
);
|
|
6457
6574
|
return { files, totalSize, perItemSizes };
|
|
6458
6575
|
}
|
|
6576
|
+
/**
|
|
6577
|
+
* Collect staged prefix `.pyc` files for vendor packages, keyed under
|
|
6578
|
+
* `_vc_pycache/<runtimeRoot>/...` (`runtimeRoot` = `/var/task/_vendor`
|
|
6579
|
+
* for bundled packages, the /tmp site-packages dir for externalized
|
|
6580
|
+
* ones). Missing staged files are silently skipped. Must be called after
|
|
6581
|
+
* `analyze()`.
|
|
6582
|
+
*/
|
|
6583
|
+
async collectPrefixBytecodeFiles({
|
|
6584
|
+
stagingDir,
|
|
6585
|
+
runtimeRoot,
|
|
6586
|
+
includePackages
|
|
6587
|
+
}) {
|
|
6588
|
+
if (!this.sitePackageDirs || !this.distributions) {
|
|
6589
|
+
throw new Error(
|
|
6590
|
+
"collectPrefixBytecodeFiles() must be called after analyze()"
|
|
6591
|
+
);
|
|
6592
|
+
}
|
|
6593
|
+
if (this.pythonMajor == null || this.pythonMinor == null) {
|
|
6594
|
+
return { files: {}, totalSize: 0, perItemSizes: /* @__PURE__ */ new Map() };
|
|
6595
|
+
}
|
|
6596
|
+
const includeSet = includePackages ? new Set(includePackages.map(import_python_analysis3.normalizePackageName)) : null;
|
|
6597
|
+
const pending = [];
|
|
6598
|
+
for (const dir of this.sitePackageDirs) {
|
|
6599
|
+
const dirDistributions = this.distributions.get(dir);
|
|
6600
|
+
if (!dirDistributions)
|
|
6601
|
+
continue;
|
|
6602
|
+
const resolvedDir = (0, import_path7.resolve)(dir);
|
|
6603
|
+
const dirPrefix = resolvedDir + import_path7.sep;
|
|
6604
|
+
for (const [name, dist] of dirDistributions) {
|
|
6605
|
+
if (includeSet && !includeSet.has(name))
|
|
6606
|
+
continue;
|
|
6607
|
+
for (const { path: rawPath } of dist.files) {
|
|
6608
|
+
if (!rawPath.endsWith(".py"))
|
|
6609
|
+
continue;
|
|
6610
|
+
const filePath = rawPath.replaceAll("/", import_path7.sep);
|
|
6611
|
+
if (!(0, import_path7.resolve)(resolvedDir, filePath).startsWith(dirPrefix)) {
|
|
6612
|
+
continue;
|
|
6613
|
+
}
|
|
6614
|
+
const srcFsPath = deriveStagedPycFsPath(
|
|
6615
|
+
stagingDir,
|
|
6616
|
+
(0, import_path7.join)(dir, filePath),
|
|
6617
|
+
this.pythonMajor,
|
|
6618
|
+
this.pythonMinor
|
|
6619
|
+
);
|
|
6620
|
+
const bundlePath = derivePrefixPycBundlePath(
|
|
6621
|
+
`${runtimeRoot}/${rawPath}`,
|
|
6622
|
+
this.pythonMajor,
|
|
6623
|
+
this.pythonMinor
|
|
6624
|
+
);
|
|
6625
|
+
if (!srcFsPath || !bundlePath)
|
|
6626
|
+
continue;
|
|
6627
|
+
pending.push({ bundlePath, srcFsPath, packageName: name });
|
|
6628
|
+
}
|
|
6629
|
+
}
|
|
6630
|
+
}
|
|
6631
|
+
const results = await Promise.all(
|
|
6632
|
+
pending.map(async ({ bundlePath, srcFsPath, packageName }) => {
|
|
6633
|
+
try {
|
|
6634
|
+
const stats = await import_fs6.default.promises.stat(srcFsPath);
|
|
6635
|
+
return { bundlePath, srcFsPath, size: stats.size, packageName };
|
|
6636
|
+
} catch {
|
|
6637
|
+
return null;
|
|
6638
|
+
}
|
|
6639
|
+
})
|
|
6640
|
+
);
|
|
6641
|
+
const files = {};
|
|
6642
|
+
let totalSize = 0;
|
|
6643
|
+
const perItemSizes = /* @__PURE__ */ new Map();
|
|
6644
|
+
for (const result of results) {
|
|
6645
|
+
if (!result)
|
|
6646
|
+
continue;
|
|
6647
|
+
files[result.bundlePath] = new import_build_utils7.FileFsRef({
|
|
6648
|
+
fsPath: result.srcFsPath,
|
|
6649
|
+
size: result.size
|
|
6650
|
+
});
|
|
6651
|
+
totalSize += result.size;
|
|
6652
|
+
perItemSizes.set(
|
|
6653
|
+
result.packageName,
|
|
6654
|
+
(perItemSizes.get(result.packageName) ?? 0) + result.size
|
|
6655
|
+
);
|
|
6656
|
+
}
|
|
6657
|
+
(0, import_build_utils7.debug)(
|
|
6658
|
+
`Collected ${Object.keys(files).length} prefix bytecode files (${(totalSize / (1024 * 1024)).toFixed(2)} MB) for runtime root ${runtimeRoot}` + (includePackages ? ` from ${includePackages.length} packages` : "")
|
|
6659
|
+
);
|
|
6660
|
+
return { files, totalSize, perItemSizes };
|
|
6661
|
+
}
|
|
6459
6662
|
};
|
|
6460
6663
|
async function getPackagesReachableOnPlatform(lockFile, projectName, pythonMajor, pythonMinor, sysPlatform, platformMachine) {
|
|
6461
6664
|
if (!projectName)
|
|
@@ -6551,12 +6754,6 @@ async function calculateBundleSize(files, filter) {
|
|
|
6551
6754
|
}
|
|
6552
6755
|
return totalSize;
|
|
6553
6756
|
}
|
|
6554
|
-
var PYC_TO_PY_RATIO = 1.2;
|
|
6555
|
-
var BYTECODE_COVERAGE_FLOOR = 0.5;
|
|
6556
|
-
async function estimateBytecodeSize(files) {
|
|
6557
|
-
const pyBytes = await calculateBundleSize(files, (p) => p.endsWith(".py"));
|
|
6558
|
-
return PYC_TO_PY_RATIO * pyBytes;
|
|
6559
|
-
}
|
|
6560
6757
|
function lambdaKnapsack(packages, capacity) {
|
|
6561
6758
|
if (capacity <= 0) {
|
|
6562
6759
|
return [];
|
|
@@ -6572,6 +6769,23 @@ function lambdaKnapsack(packages, capacity) {
|
|
|
6572
6769
|
}
|
|
6573
6770
|
return bundled;
|
|
6574
6771
|
}
|
|
6772
|
+
function planPublicPackagePacking({
|
|
6773
|
+
publicPackageSizes,
|
|
6774
|
+
zipCapacity,
|
|
6775
|
+
bytecodeFirst
|
|
6776
|
+
}) {
|
|
6777
|
+
let totalPublicSize = 0;
|
|
6778
|
+
for (const size of publicPackageSizes.values()) {
|
|
6779
|
+
totalPublicSize += size;
|
|
6780
|
+
}
|
|
6781
|
+
if (bytecodeFirst && totalPublicSize <= EPHEMERAL_INSTALL_BUDGET_BYTES) {
|
|
6782
|
+
return { packingMode: "bytecode-first", bundledPublic: [] };
|
|
6783
|
+
}
|
|
6784
|
+
return {
|
|
6785
|
+
packingMode: "knapsack",
|
|
6786
|
+
bundledPublic: lambdaKnapsack(publicPackageSizes, zipCapacity)
|
|
6787
|
+
};
|
|
6788
|
+
}
|
|
6575
6789
|
|
|
6576
6790
|
// src/diagnostics.ts
|
|
6577
6791
|
var import_fs7 = __toESM(require("fs"));
|
|
@@ -7853,24 +8067,34 @@ var startDevServer = async (opts) => {
|
|
|
7853
8067
|
installGlobalCleanupHandlers();
|
|
7854
8068
|
const env = { ...process.env, ...meta.env || {} };
|
|
7855
8069
|
const entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
|
|
8070
|
+
const isPyprojectEntrypoint = entrypoint === "pyproject.toml";
|
|
7856
8071
|
let resolved;
|
|
7857
8072
|
const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
8073
|
+
let detected;
|
|
8074
|
+
if (isPyprojectEntrypoint) {
|
|
8075
|
+
const declaredEntrypoint = await getVercelToolsEntrypoint(
|
|
8076
|
+
workPath,
|
|
8077
|
+
opts.repoRootPath
|
|
8078
|
+
);
|
|
8079
|
+
detected = declaredEntrypoint ? { entrypoint: declaredEntrypoint } : null;
|
|
8080
|
+
} else {
|
|
8081
|
+
detected = await detectPythonEntrypoint(
|
|
8082
|
+
framework,
|
|
8083
|
+
workPath,
|
|
8084
|
+
entrypoint ? {
|
|
8085
|
+
filePath: entrypoint,
|
|
8086
|
+
// Schedule-triggered services create their own "app" wrapper dynamically.
|
|
8087
|
+
// Other services use handlerFunction as the entrypoint variable name.
|
|
8088
|
+
varName: service && (0, import_build_utils13.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
|
|
8089
|
+
} : void 0,
|
|
8090
|
+
service,
|
|
8091
|
+
opts.repoRootPath
|
|
8092
|
+
);
|
|
8093
|
+
}
|
|
7870
8094
|
let hookResult;
|
|
7871
8095
|
if (detected?.entrypoint) {
|
|
7872
8096
|
resolved = detected.entrypoint;
|
|
7873
|
-
} else {
|
|
8097
|
+
} else if (!isPyprojectEntrypoint) {
|
|
7874
8098
|
hookResult = await runFrameworkHook(framework, {
|
|
7875
8099
|
pythonEnv: env,
|
|
7876
8100
|
workPath,
|
|
@@ -7884,8 +8108,8 @@ var startDevServer = async (opts) => {
|
|
|
7884
8108
|
throw detected.error;
|
|
7885
8109
|
}
|
|
7886
8110
|
throw new import_build_utils13.NowBuildError({
|
|
7887
|
-
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
7888
|
-
message: "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
8111
|
+
code: isPyprojectEntrypoint ? "PYTHON_PYPROJECT_NOTHING_TO_BUILD" : "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
8112
|
+
message: isPyprojectEntrypoint ? 'Entrypoint "pyproject.toml" does not declare a web app. Set "tool.vercel.entrypoint" in pyproject.toml.' : "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
7889
8113
|
});
|
|
7890
8114
|
}
|
|
7891
8115
|
const { entrypoint: entry, variableName } = resolved;
|
|
@@ -8674,10 +8898,54 @@ async function runDjangoCollectStatic(venvPath, workPath, djangoPath, env, outpu
|
|
|
8674
8898
|
var import_python_analysis9 = require("@vercel/python-analysis");
|
|
8675
8899
|
|
|
8676
8900
|
// src/subscribers.ts
|
|
8901
|
+
var import_path15 = require("path");
|
|
8902
|
+
var import_fs15 = __toESM(require("fs"));
|
|
8903
|
+
var import_build_utils18 = require("@vercel/build-utils");
|
|
8904
|
+
|
|
8905
|
+
// src/module-entrypoint.ts
|
|
8677
8906
|
var import_path14 = require("path");
|
|
8678
8907
|
var import_fs14 = __toESM(require("fs"));
|
|
8679
|
-
var import_build_utils18 = require("@vercel/build-utils");
|
|
8680
8908
|
var MODULE_ATTR_RE = /^([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*):([A-Za-z_][\w]*)$/;
|
|
8909
|
+
function parseModuleEntrypoint(value) {
|
|
8910
|
+
const match = MODULE_ATTR_RE.exec(value);
|
|
8911
|
+
if (!match) {
|
|
8912
|
+
return null;
|
|
8913
|
+
}
|
|
8914
|
+
return {
|
|
8915
|
+
moduleName: match[1],
|
|
8916
|
+
variableName: match[2],
|
|
8917
|
+
filePath: `${match[1].replace(/\./g, "/")}.py`
|
|
8918
|
+
};
|
|
8919
|
+
}
|
|
8920
|
+
function getModuleEntrypointName({
|
|
8921
|
+
moduleName,
|
|
8922
|
+
variableName
|
|
8923
|
+
}) {
|
|
8924
|
+
return `${moduleName.replace(/\./g, "-")}_${variableName}`;
|
|
8925
|
+
}
|
|
8926
|
+
function safePathSegment(value) {
|
|
8927
|
+
return [...value].map((char) => {
|
|
8928
|
+
if (char === "_") {
|
|
8929
|
+
return "__";
|
|
8930
|
+
}
|
|
8931
|
+
return /[A-Za-z0-9-]/.test(char) ? char : `_${char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`;
|
|
8932
|
+
}).join("");
|
|
8933
|
+
}
|
|
8934
|
+
async function resolveExistingEntrypoint(workPath, filePath) {
|
|
8935
|
+
const candidates = [filePath, filePath.replace(/\.py$/i, "/__init__.py")];
|
|
8936
|
+
for (const candidate of candidates) {
|
|
8937
|
+
try {
|
|
8938
|
+
const stat = await import_fs14.default.promises.stat((0, import_path14.join)(workPath, candidate));
|
|
8939
|
+
if (stat.isFile()) {
|
|
8940
|
+
return candidate;
|
|
8941
|
+
}
|
|
8942
|
+
} catch {
|
|
8943
|
+
}
|
|
8944
|
+
}
|
|
8945
|
+
return null;
|
|
8946
|
+
}
|
|
8947
|
+
|
|
8948
|
+
// src/subscribers.ts
|
|
8681
8949
|
var SUBSCRIBER_OUTPUT_DIR = "_py_subscribers";
|
|
8682
8950
|
var TRIGGER_NUMBER_FIELDS = [
|
|
8683
8951
|
{
|
|
@@ -8710,14 +8978,6 @@ var SUBSCRIBER_FIELD_NAMES = /* @__PURE__ */ new Set([
|
|
|
8710
8978
|
"topics",
|
|
8711
8979
|
...TRIGGER_NUMBER_FIELDS.map(({ field }) => field)
|
|
8712
8980
|
]);
|
|
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
8981
|
function getSubscriberOutputPath(subscriberName) {
|
|
8722
8982
|
return `${SUBSCRIBER_OUTPUT_DIR}/${safePathSegment(subscriberName)}`;
|
|
8723
8983
|
}
|
|
@@ -8725,8 +8985,8 @@ function getSubscriberConsumerName(subscriberName) {
|
|
|
8725
8985
|
return (0, import_build_utils18.sanitizeConsumerName)(getSubscriberOutputPath(subscriberName));
|
|
8726
8986
|
}
|
|
8727
8987
|
async function getPyprojectSubscribers(workPath) {
|
|
8728
|
-
const pyprojectPath = (0,
|
|
8729
|
-
if (!
|
|
8988
|
+
const pyprojectPath = (0, import_path15.join)(workPath, "pyproject.toml");
|
|
8989
|
+
if (!import_fs15.default.existsSync(pyprojectPath)) {
|
|
8730
8990
|
return [];
|
|
8731
8991
|
}
|
|
8732
8992
|
const pyproject = await (0, import_build_utils18.readConfigFile)(pyprojectPath);
|
|
@@ -8764,8 +9024,13 @@ async function parseSubscriber(workPath, index, config) {
|
|
|
8764
9024
|
if (typeof config.entrypoint !== "string") {
|
|
8765
9025
|
throw subscriberError(`${label} must define string field "entrypoint"`);
|
|
8766
9026
|
}
|
|
8767
|
-
const entrypoint =
|
|
8768
|
-
|
|
9027
|
+
const entrypoint = parseModuleEntrypoint(config.entrypoint);
|
|
9028
|
+
if (!entrypoint) {
|
|
9029
|
+
throw subscriberError(
|
|
9030
|
+
`${label} has invalid entrypoint "${config.entrypoint}". Use "module:object"`
|
|
9031
|
+
);
|
|
9032
|
+
}
|
|
9033
|
+
const name = getModuleEntrypointName(entrypoint);
|
|
8769
9034
|
const existingEntrypoint = await resolveExistingEntrypoint(
|
|
8770
9035
|
workPath,
|
|
8771
9036
|
entrypoint.filePath
|
|
@@ -8784,38 +9049,6 @@ async function parseSubscriber(workPath, index, config) {
|
|
|
8784
9049
|
triggerDefaults: parseTriggerDefaults(name, config)
|
|
8785
9050
|
};
|
|
8786
9051
|
}
|
|
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
9052
|
function parseTopics(name, value) {
|
|
8820
9053
|
if (!Array.isArray(value) || value.length === 0) {
|
|
8821
9054
|
throw subscriberError(
|
|
@@ -8854,8 +9087,86 @@ function subscriberError(message) {
|
|
|
8854
9087
|
});
|
|
8855
9088
|
}
|
|
8856
9089
|
|
|
9090
|
+
// src/workflows.ts
|
|
9091
|
+
var import_path16 = require("path");
|
|
9092
|
+
var import_fs16 = __toESM(require("fs"));
|
|
9093
|
+
var import_build_utils19 = require("@vercel/build-utils");
|
|
9094
|
+
var WORKFLOW_OUTPUT_DIR = "_py_workflows";
|
|
9095
|
+
var WORKFLOW_TOPIC_PATTERN = "__wkf_*";
|
|
9096
|
+
var WORKFLOW_FIELD_NAMES = /* @__PURE__ */ new Set(["entrypoint"]);
|
|
9097
|
+
function getWorkflowOutputPath(workflowName) {
|
|
9098
|
+
return `${WORKFLOW_OUTPUT_DIR}/${safePathSegment(workflowName)}`;
|
|
9099
|
+
}
|
|
9100
|
+
function getWorkflowConsumerName(workflowName) {
|
|
9101
|
+
return (0, import_build_utils19.sanitizeConsumerName)(getWorkflowOutputPath(workflowName));
|
|
9102
|
+
}
|
|
9103
|
+
async function getPyprojectWorkflows(workPath) {
|
|
9104
|
+
const pyprojectPath = (0, import_path16.join)(workPath, "pyproject.toml");
|
|
9105
|
+
if (!import_fs16.default.existsSync(pyprojectPath)) {
|
|
9106
|
+
return [];
|
|
9107
|
+
}
|
|
9108
|
+
const pyproject = await (0, import_build_utils19.readConfigFile)(pyprojectPath);
|
|
9109
|
+
const workflows = pyproject?.tool?.vercel?.workflows;
|
|
9110
|
+
if (!workflows) {
|
|
9111
|
+
return [];
|
|
9112
|
+
}
|
|
9113
|
+
if (!Array.isArray(workflows)) {
|
|
9114
|
+
throw workflowError('"tool.vercel.workflows" must be an array');
|
|
9115
|
+
}
|
|
9116
|
+
if (workflows.length > 1) {
|
|
9117
|
+
throw workflowError(
|
|
9118
|
+
'"tool.vercel.workflows" must declare a single entrypoint that registers every workflow'
|
|
9119
|
+
);
|
|
9120
|
+
}
|
|
9121
|
+
return Promise.all(
|
|
9122
|
+
workflows.map((config, index) => parseWorkflow(workPath, index, config))
|
|
9123
|
+
);
|
|
9124
|
+
}
|
|
9125
|
+
async function parseWorkflow(workPath, index, config) {
|
|
9126
|
+
const label = `workflow #${index + 1}`;
|
|
9127
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
9128
|
+
throw workflowError(`${label} must be an object`);
|
|
9129
|
+
}
|
|
9130
|
+
for (const key of Object.keys(config)) {
|
|
9131
|
+
if (!WORKFLOW_FIELD_NAMES.has(key)) {
|
|
9132
|
+
throw workflowError(`${label} has unrecognized field "${key}"`);
|
|
9133
|
+
}
|
|
9134
|
+
}
|
|
9135
|
+
if (typeof config.entrypoint !== "string") {
|
|
9136
|
+
throw workflowError(`${label} must define string field "entrypoint"`);
|
|
9137
|
+
}
|
|
9138
|
+
const entrypoint = parseModuleEntrypoint(config.entrypoint);
|
|
9139
|
+
if (!entrypoint) {
|
|
9140
|
+
throw workflowError(
|
|
9141
|
+
`${label} has invalid entrypoint "${config.entrypoint}". Use "module:object"`
|
|
9142
|
+
);
|
|
9143
|
+
}
|
|
9144
|
+
const name = getModuleEntrypointName(entrypoint);
|
|
9145
|
+
const existingEntrypoint = await resolveExistingEntrypoint(
|
|
9146
|
+
workPath,
|
|
9147
|
+
entrypoint.filePath
|
|
9148
|
+
);
|
|
9149
|
+
if (!existingEntrypoint) {
|
|
9150
|
+
throw workflowError(
|
|
9151
|
+
`workflow "${name}" has entrypoint "${config.entrypoint}" but file "${entrypoint.filePath}" does not exist`
|
|
9152
|
+
);
|
|
9153
|
+
}
|
|
9154
|
+
return {
|
|
9155
|
+
name,
|
|
9156
|
+
entrypoint: existingEntrypoint,
|
|
9157
|
+
moduleName: entrypoint.moduleName,
|
|
9158
|
+
variableName: entrypoint.variableName
|
|
9159
|
+
};
|
|
9160
|
+
}
|
|
9161
|
+
function workflowError(message) {
|
|
9162
|
+
return new import_build_utils19.NowBuildError({
|
|
9163
|
+
code: "PYTHON_INVALID_WORKFLOW_CONFIG",
|
|
9164
|
+
message
|
|
9165
|
+
});
|
|
9166
|
+
}
|
|
9167
|
+
|
|
8857
9168
|
// src/index.ts
|
|
8858
|
-
var writeFile =
|
|
9169
|
+
var writeFile = import_fs17.default.promises.writeFile;
|
|
8859
9170
|
var PYTHON_ENTRYPOINT_DOCS_URL2 = "https://vercel.com/docs/functions/runtimes/python#python-entrypoints";
|
|
8860
9171
|
var version = -1;
|
|
8861
9172
|
function getDevSubscriberTopics(subscriber) {
|
|
@@ -8868,29 +9179,55 @@ function getDevSubscriberTopics(subscriber) {
|
|
|
8868
9179
|
}
|
|
8869
9180
|
async function getDevSidecars({
|
|
8870
9181
|
workPath,
|
|
8871
|
-
build: build2
|
|
9182
|
+
build: build2,
|
|
9183
|
+
service
|
|
8872
9184
|
}) {
|
|
8873
9185
|
const framework = build2.config?.framework;
|
|
8874
|
-
|
|
9186
|
+
const isPyprojectEntrypoint = (0, import_path17.basename)(build2.src ?? "") === "pyproject.toml";
|
|
9187
|
+
const isPyprojectService = service !== void 0 && (0, import_path17.basename)(service.entrypoint ?? "") === "pyproject.toml";
|
|
9188
|
+
if (build2.config?.middleware === true || service !== void 0 && !isPyprojectService || service === void 0 && !isPyprojectEntrypoint && (typeof framework !== "string" || !(0, import_build_utils20.isPythonFramework)(framework))) {
|
|
8875
9189
|
return [];
|
|
8876
9190
|
}
|
|
8877
9191
|
const subscribers = await getPyprojectSubscribers(workPath);
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
|
|
8884
|
-
|
|
8885
|
-
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
|
|
8893
|
-
|
|
9192
|
+
const workflows = await getPyprojectWorkflows(workPath);
|
|
9193
|
+
return [
|
|
9194
|
+
...subscribers.map(
|
|
9195
|
+
(subscriber) => ({
|
|
9196
|
+
type: "subscriber",
|
|
9197
|
+
name: subscriber.name,
|
|
9198
|
+
consumer: getSubscriberConsumerName(subscriber.name),
|
|
9199
|
+
workspace: ".",
|
|
9200
|
+
framework: typeof framework === "string" ? framework : void 0,
|
|
9201
|
+
runtime: "python",
|
|
9202
|
+
builder: {
|
|
9203
|
+
use: build2.use,
|
|
9204
|
+
src: subscriber.entrypoint,
|
|
9205
|
+
config: {
|
|
9206
|
+
handlerFunction: subscriber.variableName
|
|
9207
|
+
}
|
|
9208
|
+
},
|
|
9209
|
+
topics: getDevSubscriberTopics(subscriber)
|
|
9210
|
+
})
|
|
9211
|
+
),
|
|
9212
|
+
...workflows.map(
|
|
9213
|
+
(workflow) => ({
|
|
9214
|
+
type: "subscriber",
|
|
9215
|
+
name: workflow.name,
|
|
9216
|
+
consumer: getWorkflowConsumerName(workflow.name),
|
|
9217
|
+
workspace: ".",
|
|
9218
|
+
framework: typeof framework === "string" ? framework : void 0,
|
|
9219
|
+
runtime: "python",
|
|
9220
|
+
builder: {
|
|
9221
|
+
use: build2.use,
|
|
9222
|
+
src: workflow.entrypoint,
|
|
9223
|
+
config: {
|
|
9224
|
+
handlerFunction: workflow.variableName
|
|
9225
|
+
}
|
|
9226
|
+
},
|
|
9227
|
+
topics: [{ topic: WORKFLOW_TOPIC_PATTERN }]
|
|
9228
|
+
})
|
|
9229
|
+
)
|
|
9230
|
+
];
|
|
8894
9231
|
}
|
|
8895
9232
|
function addFiles(target, source) {
|
|
8896
9233
|
for (const [p, f] of Object.entries(source)) {
|
|
@@ -8940,6 +9277,54 @@ async function addVendorBytecodeWithinCapacity({
|
|
|
8940
9277
|
addFiles(files, selectedBytecode.files);
|
|
8941
9278
|
return capacity - selectedBytecode.totalSize;
|
|
8942
9279
|
}
|
|
9280
|
+
async function addVendorBytecodeInTiers({
|
|
9281
|
+
files,
|
|
9282
|
+
depExternalizer,
|
|
9283
|
+
vendorDir,
|
|
9284
|
+
capacity,
|
|
9285
|
+
vendorPackageTiers
|
|
9286
|
+
}) {
|
|
9287
|
+
let remainingCapacity = capacity;
|
|
9288
|
+
for (const tier of vendorPackageTiers) {
|
|
9289
|
+
if (remainingCapacity <= 0)
|
|
9290
|
+
break;
|
|
9291
|
+
if (tier && tier.length === 0)
|
|
9292
|
+
continue;
|
|
9293
|
+
const bytecodeInfo = await depExternalizer.collectBytecodeFiles({
|
|
9294
|
+
vendorDirName: vendorDir,
|
|
9295
|
+
includePackages: tier
|
|
9296
|
+
});
|
|
9297
|
+
remainingCapacity = await addVendorBytecodeWithinCapacity({
|
|
9298
|
+
files,
|
|
9299
|
+
depExternalizer,
|
|
9300
|
+
vendorDir,
|
|
9301
|
+
bytecodeInfo,
|
|
9302
|
+
capacity: remainingCapacity
|
|
9303
|
+
});
|
|
9304
|
+
}
|
|
9305
|
+
return remainingCapacity;
|
|
9306
|
+
}
|
|
9307
|
+
async function addCollectedVendorBytecode({
|
|
9308
|
+
files,
|
|
9309
|
+
capacity,
|
|
9310
|
+
collect
|
|
9311
|
+
}) {
|
|
9312
|
+
if (capacity <= 0)
|
|
9313
|
+
return capacity;
|
|
9314
|
+
const info = await collect(void 0);
|
|
9315
|
+
if (!info || info.totalSize <= 0)
|
|
9316
|
+
return capacity;
|
|
9317
|
+
if (info.totalSize <= capacity) {
|
|
9318
|
+
addFiles(files, info.files);
|
|
9319
|
+
return capacity - info.totalSize;
|
|
9320
|
+
}
|
|
9321
|
+
const selected = lambdaKnapsack(info.perItemSizes, capacity);
|
|
9322
|
+
if (selected.length === 0)
|
|
9323
|
+
return capacity;
|
|
9324
|
+
const selectedInfo = await collect(selected);
|
|
9325
|
+
addFiles(files, selectedInfo.files);
|
|
9326
|
+
return capacity - selectedInfo.totalSize;
|
|
9327
|
+
}
|
|
8943
9328
|
async function runFrameworkHook(framework, ctx) {
|
|
8944
9329
|
const hook = framework ? frameworkHooks[framework] : void 0;
|
|
8945
9330
|
return hook?.(ctx);
|
|
@@ -8953,13 +9338,13 @@ var frameworkHooks = {
|
|
|
8953
9338
|
}) => {
|
|
8954
9339
|
let baseDir = detected?.baseDir;
|
|
8955
9340
|
if (baseDir === void 0) {
|
|
8956
|
-
if (!
|
|
8957
|
-
(0,
|
|
9341
|
+
if (!import_fs17.default.existsSync((0, import_path17.join)(workPath, "manage.py"))) {
|
|
9342
|
+
(0, import_build_utils20.debug)("Django hook: no manage.py detected, skipping");
|
|
8958
9343
|
return;
|
|
8959
9344
|
}
|
|
8960
9345
|
baseDir = "";
|
|
8961
9346
|
}
|
|
8962
|
-
const djangoPath = (0,
|
|
9347
|
+
const djangoPath = (0, import_path17.join)(workPath, baseDir);
|
|
8963
9348
|
let settingsResult;
|
|
8964
9349
|
try {
|
|
8965
9350
|
settingsResult = await getDjangoSettings(djangoPath, pythonEnv);
|
|
@@ -8971,13 +9356,13 @@ Hint: activate a venv or run with \`uv run vercel dev\``;
|
|
|
8971
9356
|
} else {
|
|
8972
9357
|
detail = err?.stderr || err?.message || String(err);
|
|
8973
9358
|
}
|
|
8974
|
-
throw new
|
|
9359
|
+
throw new import_build_utils20.NowBuildError({
|
|
8975
9360
|
code: "DJANGO_SETTINGS_FAILED",
|
|
8976
9361
|
message: `Failed to read Django application settings from ${djangoPath}/manage.py:
|
|
8977
9362
|
${detail}`
|
|
8978
9363
|
});
|
|
8979
9364
|
}
|
|
8980
|
-
(0,
|
|
9365
|
+
(0, import_build_utils20.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
|
|
8981
9366
|
const { djangoSettings, settingsModule, djangoVersion } = settingsResult;
|
|
8982
9367
|
if (djangoVersion) {
|
|
8983
9368
|
console.log(`Django ${djangoVersion.join(".")} detected`);
|
|
@@ -8989,7 +9374,7 @@ ${detail}`
|
|
|
8989
9374
|
const variableName = parts.at(-1);
|
|
8990
9375
|
const rel = `${parts.slice(0, -1).join("/")}.py`;
|
|
8991
9376
|
const ep = baseDir ? `${baseDir}/${rel}` : rel;
|
|
8992
|
-
(0,
|
|
9377
|
+
(0, import_build_utils20.debug)(`Django hook: ASGI entrypoint: ${ep} (variable: ${variableName})`);
|
|
8993
9378
|
resolvedEntrypoint = { entrypoint: ep, variableName };
|
|
8994
9379
|
} else {
|
|
8995
9380
|
const wsgiApp = djangoSettings["WSGI_APPLICATION"];
|
|
@@ -8998,7 +9383,7 @@ ${detail}`
|
|
|
8998
9383
|
const variableName = parts.at(-1);
|
|
8999
9384
|
const rel = `${parts.slice(0, -1).join("/")}.py`;
|
|
9000
9385
|
const ep = baseDir ? `${baseDir}/${rel}` : rel;
|
|
9001
|
-
(0,
|
|
9386
|
+
(0, import_build_utils20.debug)(
|
|
9002
9387
|
`Django hook: WSGI entrypoint: ${ep} (variable: ${variableName})`
|
|
9003
9388
|
);
|
|
9004
9389
|
resolvedEntrypoint = { entrypoint: ep, variableName };
|
|
@@ -9006,7 +9391,7 @@ ${detail}`
|
|
|
9006
9391
|
}
|
|
9007
9392
|
let djangoStatic = null;
|
|
9008
9393
|
if (workPath && venvPath) {
|
|
9009
|
-
const outputStaticDir = (0,
|
|
9394
|
+
const outputStaticDir = (0, import_path17.join)(workPath, ".vercel", "output", "static");
|
|
9010
9395
|
djangoStatic = await runDjangoCollectStatic(
|
|
9011
9396
|
venvPath,
|
|
9012
9397
|
workPath,
|
|
@@ -9021,7 +9406,7 @@ ${detail}`
|
|
|
9021
9406
|
return {
|
|
9022
9407
|
entrypoint: resolvedEntrypoint,
|
|
9023
9408
|
djangoStatic,
|
|
9024
|
-
extraPythonPath: baseDir ? (0,
|
|
9409
|
+
extraPythonPath: baseDir ? (0, import_path17.join)(workPath, baseDir) : void 0
|
|
9025
9410
|
};
|
|
9026
9411
|
}
|
|
9027
9412
|
};
|
|
@@ -9080,23 +9465,23 @@ async function downloadFilesInWorkPath({
|
|
|
9080
9465
|
files,
|
|
9081
9466
|
meta = {}
|
|
9082
9467
|
}) {
|
|
9083
|
-
(0,
|
|
9084
|
-
let downloadedFiles = await (0,
|
|
9468
|
+
(0, import_build_utils20.debug)("Downloading user files...");
|
|
9469
|
+
let downloadedFiles = await (0, import_build_utils20.download)(files, workPath, meta);
|
|
9085
9470
|
if (meta.isDev && entrypoint) {
|
|
9086
9471
|
const normalizedEntrypoint = entrypoint.endsWith(".py") ? entrypoint : `${entrypoint}.py`;
|
|
9087
9472
|
if (!hasProp(downloadedFiles, entrypoint) && !hasProp(downloadedFiles, normalizedEntrypoint)) {
|
|
9088
|
-
throw new
|
|
9473
|
+
throw new import_build_utils20.NowBuildError({
|
|
9089
9474
|
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
9090
9475
|
message: `Configured Python entrypoint "${normalizedEntrypoint}" was not found.`,
|
|
9091
9476
|
link: PYTHON_ENTRYPOINT_DOCS_URL2,
|
|
9092
9477
|
action: "Learn More"
|
|
9093
9478
|
});
|
|
9094
9479
|
}
|
|
9095
|
-
const { devCacheDir = (0,
|
|
9096
|
-
const cacheKey = (0,
|
|
9097
|
-
const destCache = (0,
|
|
9098
|
-
await (0,
|
|
9099
|
-
downloadedFiles = await (0,
|
|
9480
|
+
const { devCacheDir = (0, import_path17.join)(workPath, ".now", "cache") } = meta;
|
|
9481
|
+
const cacheKey = (0, import_path17.basename)(entrypoint).replace(/\./g, "_");
|
|
9482
|
+
const destCache = (0, import_path17.join)(devCacheDir, cacheKey);
|
|
9483
|
+
await (0, import_build_utils20.download)(downloadedFiles, destCache);
|
|
9484
|
+
downloadedFiles = await (0, import_build_utils20.glob)("**", destCache);
|
|
9100
9485
|
workPath = destCache;
|
|
9101
9486
|
}
|
|
9102
9487
|
return workPath;
|
|
@@ -9132,7 +9517,7 @@ async function getPythonLambdaOptions({
|
|
|
9132
9517
|
sources.add(entrypoint.slice(0, -".py".length));
|
|
9133
9518
|
}
|
|
9134
9519
|
for (const sourceFile of sources) {
|
|
9135
|
-
const lambdaOptions = await (0,
|
|
9520
|
+
const lambdaOptions = await (0, import_build_utils20.getLambdaOptionsFromFunction)({
|
|
9136
9521
|
sourceFile,
|
|
9137
9522
|
config
|
|
9138
9523
|
});
|
|
@@ -9152,11 +9537,11 @@ async function installInjectedPackage({
|
|
|
9152
9537
|
projectDir,
|
|
9153
9538
|
pipPlatformArgs
|
|
9154
9539
|
}) {
|
|
9155
|
-
const localDir = (0,
|
|
9156
|
-
const isLocalDev =
|
|
9540
|
+
const localDir = (0, import_path17.join)(__dirname, "..", "..", "..", "python", name);
|
|
9541
|
+
const isLocalDev = import_fs17.default.existsSync((0, import_path17.join)(localDir, "pyproject.toml"));
|
|
9157
9542
|
const dep = envOverride || (isLocalDev ? localDir : pinned);
|
|
9158
9543
|
const noExclude = ["--exclude-newer-package", `${name}=false`];
|
|
9159
|
-
(0,
|
|
9544
|
+
(0, import_build_utils20.debug)(`Installing ${dep}`);
|
|
9160
9545
|
await uv.pip({
|
|
9161
9546
|
venvPath,
|
|
9162
9547
|
projectDir,
|
|
@@ -9182,28 +9567,37 @@ var build = async ({
|
|
|
9182
9567
|
registerPreDeploy
|
|
9183
9568
|
}) => {
|
|
9184
9569
|
let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
|
|
9185
|
-
const
|
|
9570
|
+
const isPyprojectEntrypoint = entrypoint !== void 0 && (0, import_path17.basename)(entrypoint) === "pyproject.toml";
|
|
9571
|
+
if (isPyprojectEntrypoint && entrypoint !== "pyproject.toml") {
|
|
9572
|
+
throw new import_build_utils20.NowBuildError({
|
|
9573
|
+
code: "PYTHON_INVALID_PYPROJECT_ENTRYPOINT",
|
|
9574
|
+
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".`
|
|
9575
|
+
});
|
|
9576
|
+
}
|
|
9577
|
+
const builderSpan = parentSpan ?? new import_build_utils20.Span({ name: "vc.builder" });
|
|
9186
9578
|
const framework = config?.framework;
|
|
9187
9579
|
let shouldInstallVercelWorkers = config?.hasWorkerServices === true;
|
|
9188
9580
|
let subscribers = [];
|
|
9581
|
+
let workflows = [];
|
|
9189
9582
|
let spawnEnv;
|
|
9190
9583
|
let projectInstallCommand;
|
|
9191
9584
|
let hasCustomCommand = false;
|
|
9192
9585
|
const target = getTargetPlatform(meta.isDev ?? false);
|
|
9193
|
-
(0,
|
|
9586
|
+
(0, import_build_utils20.debug)(`workPath: ${workPath}`);
|
|
9194
9587
|
workPath = await downloadFilesInWorkPath({
|
|
9195
9588
|
workPath,
|
|
9196
9589
|
files: originalFiles,
|
|
9197
9590
|
entrypoint,
|
|
9198
9591
|
meta
|
|
9199
9592
|
});
|
|
9200
|
-
if (!service && (0,
|
|
9593
|
+
if (isPyprojectEntrypoint || !service && (0, import_build_utils20.isPythonFramework)(framework)) {
|
|
9201
9594
|
subscribers = await getPyprojectSubscribers(workPath);
|
|
9202
|
-
|
|
9595
|
+
workflows = await getPyprojectWorkflows(workPath);
|
|
9596
|
+
shouldInstallVercelWorkers ||= subscribers.length > 0 || workflows.length > 0;
|
|
9203
9597
|
}
|
|
9204
9598
|
try {
|
|
9205
9599
|
if (meta.isDev) {
|
|
9206
|
-
const setupCfg = (0,
|
|
9600
|
+
const setupCfg = (0, import_path17.join)(workPath, "setup.cfg");
|
|
9207
9601
|
await writeFile(setupCfg, "[install]\nprefix=\n");
|
|
9208
9602
|
}
|
|
9209
9603
|
} catch (err) {
|
|
@@ -9212,23 +9606,36 @@ var build = async ({
|
|
|
9212
9606
|
}
|
|
9213
9607
|
let detected;
|
|
9214
9608
|
const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
|
|
9215
|
-
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9609
|
+
if (isPyprojectEntrypoint) {
|
|
9610
|
+
const declared = await getVercelToolsEntrypoint(workPath, repoRootPath);
|
|
9611
|
+
if (declared) {
|
|
9612
|
+
detected = { entrypoint: declared };
|
|
9613
|
+
} else if (subscribers.length === 0 && workflows.length === 0) {
|
|
9614
|
+
throw new import_build_utils20.NowBuildError({
|
|
9615
|
+
code: "PYTHON_PYPROJECT_NOTHING_TO_BUILD",
|
|
9616
|
+
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.'
|
|
9617
|
+
});
|
|
9618
|
+
}
|
|
9619
|
+
entrypoint = void 0;
|
|
9620
|
+
} else {
|
|
9621
|
+
detected = await detectPythonEntrypoint(
|
|
9622
|
+
config.framework,
|
|
9623
|
+
workPath,
|
|
9624
|
+
entrypoint ? {
|
|
9625
|
+
filePath: entrypoint,
|
|
9626
|
+
// For schedule-triggered jobs, the WSGI variable is always 'app' (created dynamically).
|
|
9627
|
+
// For other services, handlerFunction is used as the entrypoint variable name.
|
|
9628
|
+
varName: service && (0, import_build_utils20.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
|
|
9629
|
+
} : void 0,
|
|
9630
|
+
service,
|
|
9631
|
+
repoRootPath
|
|
9632
|
+
) ?? void 0;
|
|
9633
|
+
}
|
|
9227
9634
|
if (detected?.error && detected?.baseDir === void 0) {
|
|
9228
9635
|
throw detected?.error;
|
|
9229
9636
|
}
|
|
9230
|
-
const entryDirectory = detected?.baseDir ?? (entrypoint ? (0,
|
|
9231
|
-
const entrypointAbsDir = (0,
|
|
9637
|
+
const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path17.dirname)(entrypoint) : ".");
|
|
9638
|
+
const entrypointAbsDir = (0, import_path17.join)(workPath, entryDirectory);
|
|
9232
9639
|
const rootDir = repoRootPath ?? workPath;
|
|
9233
9640
|
const pythonPackage = await builderSpan.child("vc.builder.python.discover").trace(
|
|
9234
9641
|
() => discoverPackage({
|
|
@@ -9269,12 +9676,12 @@ var build = async ({
|
|
|
9269
9676
|
}
|
|
9270
9677
|
const uvVersion = checkUvBinaryVersion(uv.getPath());
|
|
9271
9678
|
console.log(`Using ${uvVersion}`);
|
|
9272
|
-
const venvPath = service?.name ? (0,
|
|
9273
|
-
const hasCachedVenv =
|
|
9274
|
-
const hasCachedUv =
|
|
9679
|
+
const venvPath = service?.name ? (0, import_path17.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path17.join)(workPath, ".vercel", "python", ".venv");
|
|
9680
|
+
const hasCachedVenv = import_fs17.default.existsSync((0, import_path17.join)(venvPath, "pyvenv.cfg"));
|
|
9681
|
+
const hasCachedUv = import_fs17.default.existsSync(uvCacheDir);
|
|
9275
9682
|
const restoredCache = hasCachedVenv && hasCachedUv ? "both" : hasCachedVenv ? "venv" : hasCachedUv ? "uv" : "none";
|
|
9276
9683
|
if (hasCachedVenv || hasCachedUv) {
|
|
9277
|
-
(0,
|
|
9684
|
+
(0, import_build_utils20.debug)(
|
|
9278
9685
|
`Build cache detected: venv=${hasCachedVenv}, uv-cache=${hasCachedUv}`
|
|
9279
9686
|
);
|
|
9280
9687
|
}
|
|
@@ -9286,14 +9693,14 @@ var build = async ({
|
|
|
9286
9693
|
uvCacheDir
|
|
9287
9694
|
});
|
|
9288
9695
|
});
|
|
9289
|
-
if ((0,
|
|
9696
|
+
if ((0, import_build_utils20.isPythonFramework)(framework)) {
|
|
9290
9697
|
const {
|
|
9291
9698
|
cliType,
|
|
9292
9699
|
lockfileVersion,
|
|
9293
9700
|
packageJsonPackageManager,
|
|
9294
9701
|
turboSupportsCorepackHome
|
|
9295
|
-
} = await (0,
|
|
9296
|
-
spawnEnv = (0,
|
|
9702
|
+
} = await (0, import_build_utils20.scanParentDirs)(workPath, true);
|
|
9703
|
+
spawnEnv = (0, import_build_utils20.getEnvForPackageManager)({
|
|
9297
9704
|
cliType,
|
|
9298
9705
|
lockfileVersion,
|
|
9299
9706
|
packageJsonPackageManager,
|
|
@@ -9318,13 +9725,13 @@ var build = async ({
|
|
|
9318
9725
|
let uvLockPath = null;
|
|
9319
9726
|
let uvProjectDir = null;
|
|
9320
9727
|
let projectName;
|
|
9321
|
-
await builderSpan.child(
|
|
9728
|
+
await builderSpan.child(import_build_utils20.BUILDER_INSTALLER_STEP, {
|
|
9322
9729
|
installCommand: projectInstallCommand || void 0,
|
|
9323
9730
|
runtime: "python",
|
|
9324
9731
|
"python.cache.restored": restoredCache
|
|
9325
9732
|
}).trace(async () => {
|
|
9326
9733
|
if (projectInstallCommand) {
|
|
9327
|
-
await
|
|
9734
|
+
await import_fs17.default.promises.rm(venvPath, { recursive: true, force: true });
|
|
9328
9735
|
await ensureVenv({
|
|
9329
9736
|
pythonVersion,
|
|
9330
9737
|
venvPath,
|
|
@@ -9335,7 +9742,7 @@ var build = async ({
|
|
|
9335
9742
|
console.log(
|
|
9336
9743
|
`Running "install" command: \`${projectInstallCommand}\`...`
|
|
9337
9744
|
);
|
|
9338
|
-
await (0,
|
|
9745
|
+
await (0, import_build_utils20.execCommand)(projectInstallCommand, {
|
|
9339
9746
|
env: pythonEnv,
|
|
9340
9747
|
cwd: workPath
|
|
9341
9748
|
});
|
|
@@ -9356,7 +9763,7 @@ var build = async ({
|
|
|
9356
9763
|
}
|
|
9357
9764
|
if (!assumeDepsInstalled) {
|
|
9358
9765
|
const lockCacheKey = service?.name ? `uv.lock.${service.name}` : "uv.lock";
|
|
9359
|
-
const cachedLockPath = (0,
|
|
9766
|
+
const cachedLockPath = (0, import_path17.join)(uvCacheDir, lockCacheKey);
|
|
9360
9767
|
const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
|
|
9361
9768
|
workPath,
|
|
9362
9769
|
rootDir,
|
|
@@ -9377,21 +9784,21 @@ var build = async ({
|
|
|
9377
9784
|
locked: !lockFileProvidedByUser,
|
|
9378
9785
|
pythonPlatform: target.uvPlatform
|
|
9379
9786
|
});
|
|
9380
|
-
if (lockPath &&
|
|
9381
|
-
await
|
|
9382
|
-
await
|
|
9787
|
+
if (lockPath && import_fs17.default.existsSync(lockPath)) {
|
|
9788
|
+
await import_fs17.default.promises.mkdir(uvCacheDir, { recursive: true });
|
|
9789
|
+
await import_fs17.default.promises.copyFile(lockPath, cachedLockPath);
|
|
9383
9790
|
}
|
|
9384
9791
|
}
|
|
9385
9792
|
});
|
|
9386
|
-
if ((0,
|
|
9793
|
+
if ((0, import_build_utils20.isPythonFramework)(framework)) {
|
|
9387
9794
|
const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
|
|
9388
9795
|
config?.buildCommand;
|
|
9389
|
-
await builderSpan.child(
|
|
9796
|
+
await builderSpan.child(import_build_utils20.BUILDER_COMPILE_STEP, {
|
|
9390
9797
|
buildCommand: projectBuildCommand || void 0
|
|
9391
9798
|
}).trace(async () => {
|
|
9392
9799
|
if (projectBuildCommand) {
|
|
9393
9800
|
console.log(`Running "${projectBuildCommand}"`);
|
|
9394
|
-
await (0,
|
|
9801
|
+
await (0, import_build_utils20.execCommand)(projectBuildCommand, {
|
|
9395
9802
|
env: pythonEnv,
|
|
9396
9803
|
cwd: workPath
|
|
9397
9804
|
});
|
|
@@ -9411,13 +9818,14 @@ var build = async ({
|
|
|
9411
9818
|
entrypoint,
|
|
9412
9819
|
detected
|
|
9413
9820
|
});
|
|
9414
|
-
const resolved = hookResult?.entrypoint ?? detected?.entrypoint;
|
|
9821
|
+
const resolved = isPyprojectEntrypoint ? detected?.entrypoint : hookResult?.entrypoint ?? detected?.entrypoint;
|
|
9415
9822
|
if (!resolved && detected?.error) {
|
|
9416
9823
|
throw detected?.error;
|
|
9417
9824
|
}
|
|
9418
9825
|
entrypoint = resolved?.entrypoint;
|
|
9419
|
-
|
|
9420
|
-
|
|
9826
|
+
const isWorkersOnly = !entrypoint && isPyprojectEntrypoint && (subscribers.length > 0 || workflows.length > 0);
|
|
9827
|
+
if (!entrypoint && !isWorkersOnly) {
|
|
9828
|
+
throw new import_build_utils20.NowBuildError({
|
|
9421
9829
|
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
9422
9830
|
message: "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
9423
9831
|
});
|
|
@@ -9430,7 +9838,7 @@ var build = async ({
|
|
|
9430
9838
|
envOverride: baseEnv.VERCEL_RUNTIME_PYTHON,
|
|
9431
9839
|
uv,
|
|
9432
9840
|
venvPath,
|
|
9433
|
-
projectDir: (0,
|
|
9841
|
+
projectDir: (0, import_path17.join)(workPath, entryDirectory),
|
|
9434
9842
|
pipPlatformArgs
|
|
9435
9843
|
});
|
|
9436
9844
|
if (shouldInstallVercelWorkers) {
|
|
@@ -9440,7 +9848,7 @@ var build = async ({
|
|
|
9440
9848
|
envOverride: baseEnv.VERCEL_WORKERS_PYTHON,
|
|
9441
9849
|
uv,
|
|
9442
9850
|
venvPath,
|
|
9443
|
-
projectDir: (0,
|
|
9851
|
+
projectDir: (0, import_path17.join)(workPath, entryDirectory),
|
|
9444
9852
|
pipPlatformArgs
|
|
9445
9853
|
});
|
|
9446
9854
|
}
|
|
@@ -9453,57 +9861,61 @@ var build = async ({
|
|
|
9453
9861
|
const capturedEnv = { ...pythonEnv };
|
|
9454
9862
|
const capturedCwd = workPath;
|
|
9455
9863
|
registerPreDeploy(async () => {
|
|
9456
|
-
await builderSpan.child(
|
|
9864
|
+
await builderSpan.child(import_build_utils20.BUILDER_PRE_DEPLOY_STEP, {
|
|
9457
9865
|
preDeployCommand
|
|
9458
9866
|
}).trace(async () => {
|
|
9459
9867
|
console.log(`Running pre-deploy command: \`${preDeployCommand}\``);
|
|
9460
|
-
await (0,
|
|
9868
|
+
await (0, import_build_utils20.execCommand)(preDeployCommand, {
|
|
9461
9869
|
env: capturedEnv,
|
|
9462
9870
|
cwd: capturedCwd
|
|
9463
9871
|
});
|
|
9464
9872
|
});
|
|
9465
9873
|
});
|
|
9466
9874
|
}
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
const
|
|
9473
|
-
if (
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
|
|
9875
|
+
const vendorDir = resolveVendorDir();
|
|
9876
|
+
let crons;
|
|
9877
|
+
let runtimeTrampoline;
|
|
9878
|
+
if (entrypoint) {
|
|
9879
|
+
(0, import_build_utils20.debug)("Entrypoint is", entrypoint);
|
|
9880
|
+
const moduleName = entrypointToModule(entrypoint);
|
|
9881
|
+
if (handlerFunction) {
|
|
9882
|
+
const entrypointPath = (0, import_path17.join)(workPath, entrypoint);
|
|
9883
|
+
const source = await import_fs17.default.promises.readFile(entrypointPath, "utf-8");
|
|
9884
|
+
const found = await (0, import_python_analysis9.containsTopLevelCallable)(source, handlerFunction);
|
|
9885
|
+
if (!found) {
|
|
9886
|
+
throw new import_build_utils20.NowBuildError({
|
|
9887
|
+
code: "PYTHON_HANDLER_NOT_FOUND",
|
|
9888
|
+
message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
|
|
9889
|
+
});
|
|
9890
|
+
}
|
|
9478
9891
|
}
|
|
9892
|
+
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
9893
|
+
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
9894
|
+
(0, import_build_utils20.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
9895
|
+
crons = await getServiceCrons({
|
|
9896
|
+
service,
|
|
9897
|
+
entrypoint,
|
|
9898
|
+
rawEntrypoint,
|
|
9899
|
+
handlerFunction,
|
|
9900
|
+
pythonBin: getVenvPythonBin(venvPath),
|
|
9901
|
+
env: pythonEnv,
|
|
9902
|
+
workPath
|
|
9903
|
+
});
|
|
9904
|
+
const extraTrampolineEnv = [];
|
|
9905
|
+
if (crons?.length) {
|
|
9906
|
+
const json = JSON.stringify(buildCronRouteTable(crons));
|
|
9907
|
+
(0, import_assert.default)(!json.includes("\\"), `backslash in cron route table: ${json}`);
|
|
9908
|
+
extraTrampolineEnv.push(`"__VC_CRON_ROUTES": '${json}'`);
|
|
9909
|
+
}
|
|
9910
|
+
const variableName = resolved?.variableName ?? "";
|
|
9911
|
+
runtimeTrampoline = createRuntimeTrampoline({
|
|
9912
|
+
moduleName,
|
|
9913
|
+
entrypoint: entrypointWithSuffix,
|
|
9914
|
+
vendorDir,
|
|
9915
|
+
variableName,
|
|
9916
|
+
extraEnv: extraTrampolineEnv
|
|
9917
|
+
});
|
|
9479
9918
|
}
|
|
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
9919
|
const compileAllEnabled = shouldCompileAll({
|
|
9508
9920
|
isDev: meta.isDev,
|
|
9509
9921
|
hasCustomCommand,
|
|
@@ -9540,16 +9952,16 @@ var build = async ({
|
|
|
9540
9952
|
cwd: workPath,
|
|
9541
9953
|
ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
|
|
9542
9954
|
};
|
|
9543
|
-
const files = await (0,
|
|
9955
|
+
const files = await (0, import_build_utils20.glob)("**", globOptions);
|
|
9544
9956
|
if (djangoStatic?.manifestRelPath) {
|
|
9545
|
-
files[djangoStatic.manifestRelPath] = new
|
|
9546
|
-
fsPath: (0,
|
|
9957
|
+
files[djangoStatic.manifestRelPath] = new import_build_utils20.FileFsRef({
|
|
9958
|
+
fsPath: (0, import_path17.join)(workPath, djangoStatic.manifestRelPath)
|
|
9547
9959
|
});
|
|
9548
9960
|
}
|
|
9549
9961
|
const handlerPyFilename = "vc__handler__python";
|
|
9550
9962
|
if (config.framework === "fasthtml") {
|
|
9551
9963
|
const { SESSKEY = "" } = process.env;
|
|
9552
|
-
files[".sesskey"] = new
|
|
9964
|
+
files[".sesskey"] = new import_build_utils20.FileBlob({ data: `"${SESSKEY}"` });
|
|
9553
9965
|
}
|
|
9554
9966
|
const depExternalizer = new PythonDependencyExternalizer({
|
|
9555
9967
|
venvPath,
|
|
@@ -9578,10 +9990,10 @@ var build = async ({
|
|
|
9578
9990
|
});
|
|
9579
9991
|
}
|
|
9580
9992
|
});
|
|
9581
|
-
const runCompileAllAndFillBytecode = async (capacityBytes) => {
|
|
9993
|
+
const runCompileAllAndFillBytecode = async (capacityBytes, vendorPackageTiers) => {
|
|
9582
9994
|
try {
|
|
9583
9995
|
await builderSpan.child("vc.builder.python.compileall").trace(async (compileSpan) => {
|
|
9584
|
-
const sitePackageDirs = (await getVenvSitePackagesDirs(venvPath)).filter((d) =>
|
|
9996
|
+
const sitePackageDirs = (await getVenvSitePackagesDirs(venvPath)).filter((d) => import_fs17.default.existsSync(d));
|
|
9585
9997
|
const pythonBin = getVenvPythonBin(venvPath);
|
|
9586
9998
|
console.log("Compiling Python bytecode...");
|
|
9587
9999
|
await runCompileAll({
|
|
@@ -9617,75 +10029,193 @@ var build = async ({
|
|
|
9617
10029
|
remainingCapacity
|
|
9618
10030
|
);
|
|
9619
10031
|
}
|
|
9620
|
-
|
|
9621
|
-
{
|
|
9622
|
-
vendorDirName: vendorDir
|
|
9623
|
-
}
|
|
9624
|
-
);
|
|
9625
|
-
await addVendorBytecodeWithinCapacity({
|
|
10032
|
+
await addVendorBytecodeInTiers({
|
|
9626
10033
|
files,
|
|
9627
10034
|
depExternalizer,
|
|
9628
10035
|
vendorDir,
|
|
9629
|
-
|
|
9630
|
-
|
|
10036
|
+
capacity: remainingCapacity,
|
|
10037
|
+
vendorPackageTiers: vendorPackageTiers ?? [void 0]
|
|
10038
|
+
});
|
|
10039
|
+
} catch (err) {
|
|
10040
|
+
console.log(
|
|
10041
|
+
"Bytecode precompilation failed; continuing without precompiled bytecode."
|
|
10042
|
+
);
|
|
10043
|
+
(0, import_build_utils20.debug)(`bytecode precompilation error details: ${err}`);
|
|
10044
|
+
}
|
|
10045
|
+
};
|
|
10046
|
+
const runPrefixCompileAndFill = async (bundleResult) => {
|
|
10047
|
+
const pyMajor = pythonVersion.major;
|
|
10048
|
+
const pyMinor = pythonVersion.minor;
|
|
10049
|
+
if (pyMajor == null || pyMinor == null)
|
|
10050
|
+
return;
|
|
10051
|
+
try {
|
|
10052
|
+
const currentSize = await calculateBundleSize(files);
|
|
10053
|
+
let remainingCapacity = BYTECODE_FILL_CEILING_BYTES - currentSize;
|
|
10054
|
+
if (remainingCapacity <= 0) {
|
|
10055
|
+
(0, import_build_utils20.debug)(
|
|
10056
|
+
`skipping bytecode precompilation: no zip capacity remaining (bundle is ${(currentSize / (1024 * 1024)).toFixed(2)} MB)`
|
|
10057
|
+
);
|
|
10058
|
+
return;
|
|
10059
|
+
}
|
|
10060
|
+
const stagingDir = (0, import_path17.join)(workPath, ".vercel", "python", "pycache");
|
|
10061
|
+
await import_fs17.default.promises.rm(stagingDir, { recursive: true, force: true });
|
|
10062
|
+
await import_fs17.default.promises.mkdir(stagingDir, { recursive: true });
|
|
10063
|
+
await builderSpan.child("vc.builder.python.compileall").trace(async (compileSpan) => {
|
|
10064
|
+
const sitePackageDirs = (await getVenvSitePackagesDirs(venvPath)).filter((d) => import_fs17.default.existsSync(d));
|
|
10065
|
+
const pythonBin = getVenvPythonBin(venvPath);
|
|
10066
|
+
console.log("Compiling Python bytecode...");
|
|
10067
|
+
await runCompileAll({
|
|
10068
|
+
pythonBin,
|
|
10069
|
+
filesOrDirectories: [workPath],
|
|
10070
|
+
env: pythonEnv,
|
|
10071
|
+
excludeRegex: getCompileAllAppExcludeRegex(workPath),
|
|
10072
|
+
pycachePrefix: stagingDir
|
|
10073
|
+
});
|
|
10074
|
+
await runCompileAll({
|
|
10075
|
+
pythonBin,
|
|
10076
|
+
filesOrDirectories: sitePackageDirs,
|
|
10077
|
+
env: pythonEnv,
|
|
10078
|
+
pycachePrefix: stagingDir
|
|
10079
|
+
});
|
|
10080
|
+
compileSpan.setAttributes({
|
|
10081
|
+
"python.compileall.enabled": "true",
|
|
10082
|
+
"python.compileall.mode": "pycache-prefix",
|
|
10083
|
+
"python.compileall.sitePackageDirectoryCount": String(
|
|
10084
|
+
sitePackageDirs.length
|
|
10085
|
+
)
|
|
10086
|
+
});
|
|
10087
|
+
});
|
|
10088
|
+
const beforeCount = Object.keys(files).length;
|
|
10089
|
+
const appInfo = await collectAppPrefixBytecodeFiles({
|
|
10090
|
+
stagingDir,
|
|
10091
|
+
workPath,
|
|
10092
|
+
files,
|
|
10093
|
+
runtimeTaskRoot: "/var/task",
|
|
10094
|
+
pythonMajor: pyMajor,
|
|
10095
|
+
pythonMinor: pyMinor
|
|
10096
|
+
});
|
|
10097
|
+
remainingCapacity = addBytecodeWithinCapacity(
|
|
10098
|
+
files,
|
|
10099
|
+
appInfo,
|
|
10100
|
+
remainingCapacity
|
|
10101
|
+
);
|
|
10102
|
+
const alwaysBundled = bundleResult.alwaysBundledPackages ?? [];
|
|
10103
|
+
remainingCapacity = await addCollectedVendorBytecode({
|
|
10104
|
+
files,
|
|
10105
|
+
capacity: remainingCapacity,
|
|
10106
|
+
collect: (include) => depExternalizer.collectPrefixBytecodeFiles({
|
|
10107
|
+
stagingDir,
|
|
10108
|
+
runtimeRoot: `/var/task/${vendorDir}`,
|
|
10109
|
+
includePackages: include ?? alwaysBundled
|
|
10110
|
+
})
|
|
9631
10111
|
});
|
|
10112
|
+
const externalized = bundleResult.externalizedPublicPackages ?? [];
|
|
10113
|
+
await addCollectedVendorBytecode({
|
|
10114
|
+
files,
|
|
10115
|
+
capacity: remainingCapacity,
|
|
10116
|
+
collect: (include) => depExternalizer.collectPrefixBytecodeFiles({
|
|
10117
|
+
stagingDir,
|
|
10118
|
+
runtimeRoot: `${RUNTIME_DEPS_DIR}/lib/python${pyMajor}.${pyMinor}/site-packages`,
|
|
10119
|
+
includePackages: include ?? externalized
|
|
10120
|
+
})
|
|
10121
|
+
});
|
|
10122
|
+
if (Object.keys(files).length > beforeCount) {
|
|
10123
|
+
lambdaEnv.PYTHONPYCACHEPREFIX = RUNTIME_PYCACHE_PREFIX;
|
|
10124
|
+
}
|
|
9632
10125
|
} catch (err) {
|
|
9633
10126
|
console.log(
|
|
9634
10127
|
"Bytecode precompilation failed; continuing without precompiled bytecode."
|
|
9635
10128
|
);
|
|
9636
|
-
(0,
|
|
10129
|
+
(0, import_build_utils20.debug)(`bytecode precompilation error details: ${err}`);
|
|
9637
10130
|
}
|
|
9638
10131
|
};
|
|
9639
10132
|
const announceLargeFunction = () => console.log(
|
|
9640
|
-
`Function "${entrypoint}" exceeds the standard size limit; enabling large functions (beta).`
|
|
10133
|
+
`Function "${entrypoint ?? rawEntrypoint}" exceeds the standard size limit; enabling large functions (beta).`
|
|
9641
10134
|
);
|
|
10135
|
+
let packingMode;
|
|
9642
10136
|
if (depAnalysis.runtimeInstallEnabled) {
|
|
9643
|
-
|
|
9644
|
-
|
|
10137
|
+
packingMode = "runtime-install";
|
|
10138
|
+
const bytecodeFirst = compileAllEnabled && pythonVersion.major != null && pythonVersion.minor != null;
|
|
10139
|
+
const bundleResult = await depExternalizer.generateBundle(files, {
|
|
10140
|
+
bytecodeFirst
|
|
10141
|
+
});
|
|
10142
|
+
if (bundleResult.fellBackToFullBundle) {
|
|
10143
|
+
packingMode = "hive";
|
|
9645
10144
|
announceLargeFunction();
|
|
9646
10145
|
if (compileAllEnabled) {
|
|
9647
10146
|
await runCompileAllAndFillBytecode(
|
|
9648
|
-
|
|
10147
|
+
LARGE_FUNCTION_FILL_CEILING_BYTES
|
|
10148
|
+
);
|
|
10149
|
+
}
|
|
10150
|
+
} else if (bundleResult.packingMode === "bytecode-first") {
|
|
10151
|
+
await runPrefixCompileAndFill(bundleResult);
|
|
10152
|
+
} else if (compileAllEnabled) {
|
|
10153
|
+
const currentSize = await calculateBundleSize(files);
|
|
10154
|
+
const capacity = BYTECODE_FILL_CEILING_BYTES - currentSize;
|
|
10155
|
+
if (capacity > 0) {
|
|
10156
|
+
await runCompileAllAndFillBytecode(BYTECODE_FILL_CEILING_BYTES, [
|
|
10157
|
+
bundleResult.alwaysBundledPackages ?? [],
|
|
10158
|
+
bundleResult.bundledPublicPackages ?? []
|
|
10159
|
+
]);
|
|
10160
|
+
} else {
|
|
10161
|
+
(0, import_build_utils20.debug)(
|
|
10162
|
+
`skipping bytecode precompilation: no zip capacity remaining (bundle is ${(currentSize / (1024 * 1024)).toFixed(2)} MB)`
|
|
9649
10163
|
);
|
|
9650
10164
|
}
|
|
9651
10165
|
}
|
|
9652
10166
|
} else {
|
|
9653
10167
|
addFiles(files, depAnalysis.allVendorFiles);
|
|
9654
10168
|
if (depAnalysis.totalBundleSize > LAMBDA_SIZE_THRESHOLD_BYTES) {
|
|
10169
|
+
packingMode = "hive";
|
|
9655
10170
|
if (isLargeFunctionsEnabled()) {
|
|
9656
10171
|
announceLargeFunction();
|
|
9657
10172
|
}
|
|
9658
10173
|
if (compileAllEnabled) {
|
|
9659
10174
|
await runCompileAllAndFillBytecode(
|
|
9660
|
-
|
|
10175
|
+
LARGE_FUNCTION_FILL_CEILING_BYTES
|
|
9661
10176
|
);
|
|
9662
10177
|
}
|
|
9663
|
-
} else
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
10178
|
+
} else {
|
|
10179
|
+
packingMode = "standard";
|
|
10180
|
+
if (compileAllEnabled) {
|
|
10181
|
+
const capacity = BYTECODE_FILL_CEILING_BYTES - depAnalysis.totalBundleSize;
|
|
10182
|
+
if (capacity > 0) {
|
|
10183
|
+
await runCompileAllAndFillBytecode(BYTECODE_FILL_CEILING_BYTES);
|
|
10184
|
+
} else {
|
|
10185
|
+
(0, import_build_utils20.debug)(
|
|
10186
|
+
`skipping bytecode precompilation: no zip capacity remaining (bundle is ${(depAnalysis.totalBundleSize / (1024 * 1024)).toFixed(2)} MB)`
|
|
10187
|
+
);
|
|
10188
|
+
}
|
|
9668
10189
|
}
|
|
9669
10190
|
}
|
|
9670
10191
|
}
|
|
10192
|
+
bundleSpan.setAttributes({
|
|
10193
|
+
"python.bundle.totalSizeBytes": String(
|
|
10194
|
+
await calculateBundleSize(files)
|
|
10195
|
+
),
|
|
10196
|
+
"python.bundle.packingMode": packingMode
|
|
10197
|
+
});
|
|
9671
10198
|
});
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
10199
|
+
let output;
|
|
10200
|
+
if (entrypoint && runtimeTrampoline) {
|
|
10201
|
+
const webFiles = {
|
|
10202
|
+
...files,
|
|
10203
|
+
[`${handlerPyFilename}.py`]: new import_build_utils20.FileBlob({ data: runtimeTrampoline })
|
|
10204
|
+
};
|
|
10205
|
+
const lambdaOptions = await getPythonLambdaOptions({
|
|
10206
|
+
config,
|
|
10207
|
+
entrypoint
|
|
10208
|
+
});
|
|
10209
|
+
output = new import_build_utils20.Lambda({
|
|
10210
|
+
files: webFiles,
|
|
10211
|
+
handler: `${handlerPyFilename}.vc_handler`,
|
|
10212
|
+
runtime: pythonVersion.runtime,
|
|
10213
|
+
...lambdaOptions,
|
|
10214
|
+
architecture: target.architecture,
|
|
10215
|
+
environment: lambdaEnv,
|
|
10216
|
+
supportsResponseStreaming: true
|
|
10217
|
+
});
|
|
10218
|
+
}
|
|
9689
10219
|
const subscriberLambdas = {};
|
|
9690
10220
|
for (const subscriber of subscribers) {
|
|
9691
10221
|
const outputPath = getSubscriberOutputPath(subscriber.name);
|
|
@@ -9698,10 +10228,10 @@ var build = async ({
|
|
|
9698
10228
|
...subscriber.triggerDefaults
|
|
9699
10229
|
})
|
|
9700
10230
|
);
|
|
9701
|
-
subscriberLambdas[outputPath] = new
|
|
10231
|
+
subscriberLambdas[outputPath] = new import_build_utils20.Lambda({
|
|
9702
10232
|
files: {
|
|
9703
10233
|
...files,
|
|
9704
|
-
[`${handlerPyFilename}.py`]: new
|
|
10234
|
+
[`${handlerPyFilename}.py`]: new import_build_utils20.FileBlob({
|
|
9705
10235
|
data: createRuntimeTrampoline({
|
|
9706
10236
|
moduleName: subscriber.moduleName,
|
|
9707
10237
|
entrypoint: subscriber.entrypoint,
|
|
@@ -9723,6 +10253,41 @@ var build = async ({
|
|
|
9723
10253
|
supportsResponseStreaming: true
|
|
9724
10254
|
});
|
|
9725
10255
|
}
|
|
10256
|
+
const workflowLambdas = {};
|
|
10257
|
+
for (const workflow of workflows) {
|
|
10258
|
+
const outputPath = getWorkflowOutputPath(workflow.name);
|
|
10259
|
+
const experimentalTriggers = [
|
|
10260
|
+
{
|
|
10261
|
+
type: "queue/v2beta",
|
|
10262
|
+
topic: WORKFLOW_TOPIC_PATTERN,
|
|
10263
|
+
consumer: getWorkflowConsumerName(workflow.name)
|
|
10264
|
+
}
|
|
10265
|
+
];
|
|
10266
|
+
workflowLambdas[outputPath] = new import_build_utils20.Lambda({
|
|
10267
|
+
files: {
|
|
10268
|
+
...files,
|
|
10269
|
+
[`${handlerPyFilename}.py`]: new import_build_utils20.FileBlob({
|
|
10270
|
+
data: createRuntimeTrampoline({
|
|
10271
|
+
moduleName: workflow.moduleName,
|
|
10272
|
+
entrypoint: workflow.entrypoint,
|
|
10273
|
+
vendorDir,
|
|
10274
|
+
variableName: workflow.variableName
|
|
10275
|
+
})
|
|
10276
|
+
})
|
|
10277
|
+
},
|
|
10278
|
+
handler: `${handlerPyFilename}.vc_handler`,
|
|
10279
|
+
runtime: pythonVersion.runtime,
|
|
10280
|
+
architecture: target.architecture,
|
|
10281
|
+
environment: {
|
|
10282
|
+
...lambdaEnv,
|
|
10283
|
+
VERCEL_HAS_WORKER_SERVICES: "1",
|
|
10284
|
+
// Compatibility marker consumed by the current Python runtime.
|
|
10285
|
+
VERCEL_SERVICE_TYPE: "worker"
|
|
10286
|
+
},
|
|
10287
|
+
experimentalTriggers,
|
|
10288
|
+
supportsResponseStreaming: true
|
|
10289
|
+
});
|
|
10290
|
+
}
|
|
9726
10291
|
if (uvLockPath && !meta.isDev) {
|
|
9727
10292
|
try {
|
|
9728
10293
|
await generateProjectManifest({
|
|
@@ -9731,21 +10296,22 @@ var build = async ({
|
|
|
9731
10296
|
pythonVersion,
|
|
9732
10297
|
uvLockPath,
|
|
9733
10298
|
framework,
|
|
9734
|
-
serviceType: service ? (0,
|
|
10299
|
+
serviceType: service ? (0, import_build_utils20.getReportedServiceType)(service) : void 0
|
|
9735
10300
|
});
|
|
9736
10301
|
} catch (err) {
|
|
9737
|
-
(0,
|
|
10302
|
+
(0, import_build_utils20.debug)(
|
|
9738
10303
|
`Failed to write project manifest: ${err instanceof Error ? err.message : String(err)}`
|
|
9739
10304
|
);
|
|
9740
10305
|
}
|
|
9741
10306
|
}
|
|
9742
|
-
if (!(0,
|
|
10307
|
+
if (!(0, import_build_utils20.isPythonFramework)(framework) && !service?.name && !isPyprojectEntrypoint) {
|
|
10308
|
+
(0, import_assert.default)(output, "web Lambda must exist for non-service builds");
|
|
9743
10309
|
return { resultVersion: 3, result: { output } };
|
|
9744
10310
|
}
|
|
9745
10311
|
const lambdaPath = service?.name && service.type ? `_svc/${service.name}/index` : "index";
|
|
9746
|
-
const staticFiles = djangoStatic?.cdnOutputDir ? await (0,
|
|
10312
|
+
const staticFiles = djangoStatic?.cdnOutputDir ? await (0, import_build_utils20.glob)("**", { cwd: djangoStatic.cdnOutputDir }) : {};
|
|
9747
10313
|
const isNonWebService = service?.name && service.type && service.type !== "web";
|
|
9748
|
-
const routes = isNonWebService ? void 0 : [
|
|
10314
|
+
const routes = isNonWebService || !output ? void 0 : [
|
|
9749
10315
|
{ handle: "filesystem" },
|
|
9750
10316
|
{ src: "/(.*)", dest: `/${lambdaPath}` }
|
|
9751
10317
|
];
|
|
@@ -9753,8 +10319,9 @@ var build = async ({
|
|
|
9753
10319
|
resultVersion: 2,
|
|
9754
10320
|
result: {
|
|
9755
10321
|
output: {
|
|
9756
|
-
[lambdaPath]: output,
|
|
10322
|
+
...output ? { [lambdaPath]: output } : {},
|
|
9757
10323
|
...subscriberLambdas,
|
|
10324
|
+
...workflowLambdas,
|
|
9758
10325
|
...staticFiles
|
|
9759
10326
|
},
|
|
9760
10327
|
...routes ? { routes } : {},
|
|
@@ -9777,14 +10344,14 @@ var prepareCache = async ({
|
|
|
9777
10344
|
}
|
|
9778
10345
|
} catch {
|
|
9779
10346
|
}
|
|
9780
|
-
return (0,
|
|
10347
|
+
return (0, import_build_utils20.glob)("**/.vercel/python/{.venv,services/*/.venv,cache/uv}/**", {
|
|
9781
10348
|
cwd: root,
|
|
9782
10349
|
ignore
|
|
9783
10350
|
});
|
|
9784
10351
|
};
|
|
9785
10352
|
var shouldServe = (opts) => {
|
|
9786
10353
|
const framework = opts.config.framework;
|
|
9787
|
-
if ((0,
|
|
10354
|
+
if ((0, import_build_utils20.isPythonFramework)(framework)) {
|
|
9788
10355
|
const requestPath = opts.requestPath.replace(/\/$/, "");
|
|
9789
10356
|
if (requestPath.startsWith("api") && opts.hasMatched) {
|
|
9790
10357
|
return false;
|
|
@@ -9803,7 +10370,7 @@ var defaultShouldServe = ({
|
|
|
9803
10370
|
if (entrypoint === requestPath && hasProp(files, entrypoint)) {
|
|
9804
10371
|
return true;
|
|
9805
10372
|
}
|
|
9806
|
-
const { dir, name } = (0,
|
|
10373
|
+
const { dir, name } = (0, import_path17.parse)(entrypoint);
|
|
9807
10374
|
if (name === "index" && dir === requestPath && hasProp(files, entrypoint)) {
|
|
9808
10375
|
return true;
|
|
9809
10376
|
}
|
|
@@ -9814,6 +10381,8 @@ function hasProp(obj, key) {
|
|
|
9814
10381
|
}
|
|
9815
10382
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9816
10383
|
0 && (module.exports = {
|
|
10384
|
+
addCollectedVendorBytecode,
|
|
10385
|
+
addVendorBytecodeInTiers,
|
|
9817
10386
|
build,
|
|
9818
10387
|
defaultShouldServe,
|
|
9819
10388
|
detectEntrypoint,
|