@vercel/python 6.48.0 → 6.49.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 +284 -128
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4366,6 +4366,7 @@ __export(src_exports, {
|
|
|
4366
4366
|
detectEntrypoint: () => detectEntrypoint,
|
|
4367
4367
|
diagnostics: () => diagnostics,
|
|
4368
4368
|
downloadFilesInWorkPath: () => downloadFilesInWorkPath,
|
|
4369
|
+
getDevSidecars: () => getDevSidecars,
|
|
4369
4370
|
installRequirement: () => installRequirement,
|
|
4370
4371
|
installRequirementsFile: () => installRequirementsFile,
|
|
4371
4372
|
prepareCache: () => prepareCache,
|
|
@@ -5649,33 +5650,26 @@ var import_execa4 = __toESM(require_execa());
|
|
|
5649
5650
|
var import_build_utils6 = require("@vercel/build-utils");
|
|
5650
5651
|
var import_fs5 = __toESM(require("fs"));
|
|
5651
5652
|
var import_path6 = require("path");
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
function isLargeFunctionsEnabled() {
|
|
5655
|
-
const value = process.env.VERCEL_SUPPORT_LARGE_FUNCTIONS;
|
|
5656
|
-
return value === "1" || value === "true";
|
|
5657
|
-
}
|
|
5658
|
-
|
|
5659
|
-
// src/compileall.ts
|
|
5660
|
-
function isCompileAllEnabled() {
|
|
5661
|
-
if (!isLargeFunctionsEnabled())
|
|
5662
|
-
return false;
|
|
5653
|
+
var COMPILEALL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
5654
|
+
function isCompileAllFlagEnabled() {
|
|
5663
5655
|
const val = process.env.VERCEL_PYTHON_COMPILEALL;
|
|
5664
5656
|
if (val === void 0 || val === "")
|
|
5665
5657
|
return false;
|
|
5666
5658
|
const lower = val.toLowerCase();
|
|
5667
5659
|
return lower === "1" || lower === "true";
|
|
5668
5660
|
}
|
|
5669
|
-
function
|
|
5661
|
+
function shouldCompileAll({
|
|
5670
5662
|
isDev,
|
|
5671
5663
|
hasCustomCommand,
|
|
5672
|
-
|
|
5664
|
+
hasPreDeployCommand
|
|
5673
5665
|
}) {
|
|
5674
5666
|
if (isDev)
|
|
5675
5667
|
return false;
|
|
5676
|
-
if (hasCustomCommand
|
|
5668
|
+
if (hasCustomCommand)
|
|
5669
|
+
return false;
|
|
5670
|
+
if (hasPreDeployCommand)
|
|
5677
5671
|
return false;
|
|
5678
|
-
return
|
|
5672
|
+
return isCompileAllFlagEnabled();
|
|
5679
5673
|
}
|
|
5680
5674
|
async function runCompileAll({
|
|
5681
5675
|
pythonBin,
|
|
@@ -5698,7 +5692,10 @@ async function runCompileAll({
|
|
|
5698
5692
|
...filesOrDirectories
|
|
5699
5693
|
];
|
|
5700
5694
|
try {
|
|
5701
|
-
await (0, import_execa4.default)(pythonBin, args, {
|
|
5695
|
+
await (0, import_execa4.default)(pythonBin, args, {
|
|
5696
|
+
env: env || process.env,
|
|
5697
|
+
timeout: COMPILEALL_TIMEOUT_MS
|
|
5698
|
+
});
|
|
5702
5699
|
} catch (err) {
|
|
5703
5700
|
(0, import_build_utils6.debug)(`compileall error details: ${JSON.stringify(err)}`);
|
|
5704
5701
|
}
|
|
@@ -5774,6 +5771,12 @@ async function collectAppBytecodeFiles({
|
|
|
5774
5771
|
return { files, totalSize, perItemSizes };
|
|
5775
5772
|
}
|
|
5776
5773
|
|
|
5774
|
+
// src/large-functions.ts
|
|
5775
|
+
function isLargeFunctionsEnabled() {
|
|
5776
|
+
const value = process.env.VERCEL_SUPPORT_LARGE_FUNCTIONS;
|
|
5777
|
+
return value === "1" || value === "true";
|
|
5778
|
+
}
|
|
5779
|
+
|
|
5777
5780
|
// src/dependency-externalizer.ts
|
|
5778
5781
|
var readFile = (0, import_util.promisify)(import_fs6.default.readFile);
|
|
5779
5782
|
var STRIP_BASENAMES = /* @__PURE__ */ new Set([
|
|
@@ -5794,6 +5797,8 @@ function shouldStripVendorFile(filePath) {
|
|
|
5794
5797
|
return false;
|
|
5795
5798
|
}
|
|
5796
5799
|
var LAMBDA_SIZE_THRESHOLD_BYTES = 225 * 1024 * 1024;
|
|
5800
|
+
var BYTECODE_FILL_MARGIN_BYTES = 5 * 1024 * 1024;
|
|
5801
|
+
var BYTECODE_FILL_CEILING_BYTES = LAMBDA_SIZE_THRESHOLD_BYTES - BYTECODE_FILL_MARGIN_BYTES;
|
|
5797
5802
|
var LAMBDA_EPHEMERAL_STORAGE_BYTES = 500 * 1024 * 1024;
|
|
5798
5803
|
var MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE = 5 * 1024 * 1024 * 1024;
|
|
5799
5804
|
var BUNDLING_DOCS_LINK = "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled";
|
|
@@ -6510,10 +6515,12 @@ async function getPackagesReachableOnPlatform(lockFile, projectName, pythonMajor
|
|
|
6510
6515
|
}
|
|
6511
6516
|
return visited;
|
|
6512
6517
|
}
|
|
6513
|
-
async function calculateBundleSize(files) {
|
|
6518
|
+
async function calculateBundleSize(files, filter) {
|
|
6514
6519
|
let knownSize = 0;
|
|
6515
6520
|
const statPromises = [];
|
|
6516
6521
|
for (const filePath of Object.keys(files)) {
|
|
6522
|
+
if (filter && !filter(filePath))
|
|
6523
|
+
continue;
|
|
6517
6524
|
const file = files[filePath];
|
|
6518
6525
|
if ("fsPath" in file && file.fsPath) {
|
|
6519
6526
|
const fsRef = file;
|
|
@@ -6521,7 +6528,10 @@ async function calculateBundleSize(files) {
|
|
|
6521
6528
|
knownSize += fsRef.size;
|
|
6522
6529
|
} else {
|
|
6523
6530
|
statPromises.push(
|
|
6524
|
-
import_fs6.default.promises.stat(fsRef.fsPath).then((stats) =>
|
|
6531
|
+
import_fs6.default.promises.stat(fsRef.fsPath).then((stats) => {
|
|
6532
|
+
fsRef.size = stats.size;
|
|
6533
|
+
return stats.size;
|
|
6534
|
+
}).catch((err) => {
|
|
6525
6535
|
console.warn(
|
|
6526
6536
|
`Warning: Failed to stat file ${fsRef.fsPath}, size will not be included in bundle calculation: ${err}`
|
|
6527
6537
|
);
|
|
@@ -6541,6 +6551,12 @@ async function calculateBundleSize(files) {
|
|
|
6541
6551
|
}
|
|
6542
6552
|
return totalSize;
|
|
6543
6553
|
}
|
|
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
|
+
}
|
|
6544
6560
|
function lambdaKnapsack(packages, capacity) {
|
|
6545
6561
|
if (capacity <= 0) {
|
|
6546
6562
|
return [];
|
|
@@ -6870,7 +6886,7 @@ function getMissingExportMessage(framework, entrypoints) {
|
|
|
6870
6886
|
}
|
|
6871
6887
|
}
|
|
6872
6888
|
function entrypointToModule(entrypoint) {
|
|
6873
|
-
return entrypoint.replace(/\\/g, "/").replace(/\.py$/i, "").replace(/\//g, ".");
|
|
6889
|
+
return entrypoint.replace(/\\/g, "/").replace(/\.py$/i, "").replace(/\/__init__$/i, "").replace(/\//g, ".");
|
|
6874
6890
|
}
|
|
6875
6891
|
async function checkEntrypoint(workPath, relPath) {
|
|
6876
6892
|
const absPath = (0, import_path8.join)(workPath, relPath);
|
|
@@ -6946,14 +6962,37 @@ async function resolveModuleAttrEntrypoint(workPath, value) {
|
|
|
6946
6962
|
}
|
|
6947
6963
|
return null;
|
|
6948
6964
|
}
|
|
6949
|
-
async function getVercelToolsEntrypoint(workPath) {
|
|
6950
|
-
const
|
|
6965
|
+
async function getVercelToolsEntrypoint(workPath, repoRootPath) {
|
|
6966
|
+
const pyprojectPath = (0, import_path8.join)(workPath, "pyproject.toml");
|
|
6967
|
+
const pyprojectData = await (0, import_build_utils11.readConfigFile)(pyprojectPath);
|
|
6951
6968
|
if (!pyprojectData)
|
|
6952
6969
|
return null;
|
|
6953
6970
|
const vercelEntrypoint = pyprojectData.tool?.vercel?.entrypoint;
|
|
6954
|
-
if (
|
|
6971
|
+
if (vercelEntrypoint === void 0)
|
|
6955
6972
|
return null;
|
|
6956
|
-
|
|
6973
|
+
const relPyprojectPath = (0, import_path8.relative)(repoRootPath ?? workPath, pyprojectPath);
|
|
6974
|
+
const displayPath = !relPyprojectPath || relPyprojectPath.startsWith("..") ? pyprojectPath : relPyprojectPath;
|
|
6975
|
+
if (typeof vercelEntrypoint !== "string") {
|
|
6976
|
+
throw new import_build_utils9.NowBuildError({
|
|
6977
|
+
code: "PYTHON_INVALID_ENTRYPOINT",
|
|
6978
|
+
message: `"tool.vercel.entrypoint" in "${displayPath}" must be a string in "module:object" format (e.g. "main:app").`,
|
|
6979
|
+
link: PYTHON_ENTRYPOINT_DOCS_URL,
|
|
6980
|
+
action: "Learn More"
|
|
6981
|
+
});
|
|
6982
|
+
}
|
|
6983
|
+
const resolved = await resolveModuleAttrEntrypoint(
|
|
6984
|
+
workPath,
|
|
6985
|
+
vercelEntrypoint
|
|
6986
|
+
);
|
|
6987
|
+
if (!resolved) {
|
|
6988
|
+
throw new import_build_utils9.NowBuildError({
|
|
6989
|
+
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
6990
|
+
message: `"tool.vercel.entrypoint" in "${displayPath}" is "${vercelEntrypoint}" but no matching module file was found. Use "module:object" format (e.g. "main:app") and ensure the module file exists, or remove the setting to use automatic entrypoint detection.`,
|
|
6991
|
+
link: PYTHON_ENTRYPOINT_DOCS_URL,
|
|
6992
|
+
action: "Learn More"
|
|
6993
|
+
});
|
|
6994
|
+
}
|
|
6995
|
+
return resolved;
|
|
6957
6996
|
}
|
|
6958
6997
|
async function getPyprojectEntrypointWithDiagnostics(workPath) {
|
|
6959
6998
|
const pyprojectData = await (0, import_build_utils11.readConfigFile)((0, import_path8.join)(workPath, "pyproject.toml"));
|
|
@@ -7107,7 +7146,7 @@ async function detectDjangoPythonEntrypoint(workPath) {
|
|
|
7107
7146
|
return emptyResult;
|
|
7108
7147
|
}
|
|
7109
7148
|
}
|
|
7110
|
-
async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint, service) {
|
|
7149
|
+
async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint, service, repoRootPath) {
|
|
7111
7150
|
if (configuredEntrypoint) {
|
|
7112
7151
|
const { filePath: configEntryFile, varName: configEntryVar } = configuredEntrypoint;
|
|
7113
7152
|
const entrypoint = configEntryFile.endsWith(".py") ? configEntryFile : `${configEntryFile}.py`;
|
|
@@ -7146,7 +7185,7 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint,
|
|
|
7146
7185
|
if (!framework) {
|
|
7147
7186
|
return null;
|
|
7148
7187
|
}
|
|
7149
|
-
const vercelEntry = await getVercelToolsEntrypoint(workPath);
|
|
7188
|
+
const vercelEntry = await getVercelToolsEntrypoint(workPath, repoRootPath);
|
|
7150
7189
|
if (vercelEntry)
|
|
7151
7190
|
return { entrypoint: vercelEntry };
|
|
7152
7191
|
let findDiagnostics;
|
|
@@ -7186,10 +7225,18 @@ var detectEntrypoint = async ({
|
|
|
7186
7225
|
}) => {
|
|
7187
7226
|
if (!(0, import_build_utils9.isPythonFramework)(framework))
|
|
7188
7227
|
return null;
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7228
|
+
let detected;
|
|
7229
|
+
try {
|
|
7230
|
+
detected = await detectPythonEntrypoint(
|
|
7231
|
+
framework,
|
|
7232
|
+
workPath
|
|
7233
|
+
);
|
|
7234
|
+
} catch (err) {
|
|
7235
|
+
(0, import_build_utils10.debug)(
|
|
7236
|
+
`Python entrypoint detection failed for ${workPath}: ${err instanceof Error ? err.message : String(err)}`
|
|
7237
|
+
);
|
|
7238
|
+
return null;
|
|
7239
|
+
}
|
|
7193
7240
|
if (!detected?.entrypoint)
|
|
7194
7241
|
return null;
|
|
7195
7242
|
const { entrypoint, variableName } = detected.entrypoint;
|
|
@@ -7415,6 +7462,23 @@ async function getReachableHost(port) {
|
|
|
7415
7462
|
]);
|
|
7416
7463
|
return results.find(Boolean) || false;
|
|
7417
7464
|
}
|
|
7465
|
+
async function dedupePendingOperation(operations, key, operation) {
|
|
7466
|
+
const existing = operations.get(key);
|
|
7467
|
+
if (existing) {
|
|
7468
|
+
return existing;
|
|
7469
|
+
}
|
|
7470
|
+
const pending = operation();
|
|
7471
|
+
operations.set(key, pending);
|
|
7472
|
+
try {
|
|
7473
|
+
return await pending;
|
|
7474
|
+
} finally {
|
|
7475
|
+
if (operations.get(key) === pending) {
|
|
7476
|
+
operations.delete(key);
|
|
7477
|
+
}
|
|
7478
|
+
}
|
|
7479
|
+
}
|
|
7480
|
+
var PENDING_MANAGED_VENV_CREATIONS = /* @__PURE__ */ new Map();
|
|
7481
|
+
var PENDING_DEPENDENCY_SYNCS = /* @__PURE__ */ new Map();
|
|
7418
7482
|
async function syncDependencies({
|
|
7419
7483
|
workPath,
|
|
7420
7484
|
uvPath,
|
|
@@ -7558,16 +7622,29 @@ async function runSync({
|
|
|
7558
7622
|
});
|
|
7559
7623
|
}
|
|
7560
7624
|
var PENDING_INSTALLS = /* @__PURE__ */ new Map();
|
|
7625
|
+
var COMPLETED_INSTALLS = /* @__PURE__ */ new Set();
|
|
7626
|
+
function hasInstalledDistribution(targetDir, packageName) {
|
|
7627
|
+
const prefix = `${packageName.replace("-", "_")}-`;
|
|
7628
|
+
try {
|
|
7629
|
+
return (0, import_fs10.readdirSync)(targetDir).some(
|
|
7630
|
+
(entry) => entry.startsWith(prefix) && entry.endsWith(".dist-info")
|
|
7631
|
+
);
|
|
7632
|
+
} catch {
|
|
7633
|
+
return false;
|
|
7634
|
+
}
|
|
7635
|
+
}
|
|
7561
7636
|
async function installInjectedDevPackage(pkg, opts) {
|
|
7562
7637
|
const targetDir = (0, import_path10.join)(opts.workPath, ".vercel", "python");
|
|
7563
|
-
const
|
|
7564
|
-
|
|
7565
|
-
if (
|
|
7566
|
-
|
|
7567
|
-
PENDING_INSTALLS.set(key, pending);
|
|
7568
|
-
pending.finally(() => PENDING_INSTALLS.delete(key));
|
|
7638
|
+
const source = pkg.envOverride || pkg.pinnedVersion;
|
|
7639
|
+
const key = `${targetDir}:${pkg.name}:${source}`;
|
|
7640
|
+
if (COMPLETED_INSTALLS.has(key) && hasInstalledDistribution(targetDir, pkg.name)) {
|
|
7641
|
+
return;
|
|
7569
7642
|
}
|
|
7570
|
-
|
|
7643
|
+
COMPLETED_INSTALLS.delete(key);
|
|
7644
|
+
await dedupePendingOperation(PENDING_INSTALLS, key, async () => {
|
|
7645
|
+
await doInstallInjectedDevPackage(pkg, { ...opts, targetDir });
|
|
7646
|
+
COMPLETED_INSTALLS.add(key);
|
|
7647
|
+
});
|
|
7571
7648
|
}
|
|
7572
7649
|
async function doInstallInjectedDevPackage(pkg, opts) {
|
|
7573
7650
|
const { targetDir, workPath, uvPath, pythonBin, env, onStdout, onStderr } = opts;
|
|
@@ -7707,18 +7784,26 @@ function createDevShim(workPath, entry, modulePath, serviceName, framework, vari
|
|
|
7707
7784
|
}
|
|
7708
7785
|
}
|
|
7709
7786
|
async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath) {
|
|
7787
|
+
const venvPath = (0, import_path10.join)(workPath, ".venv");
|
|
7788
|
+
const pendingCreation = PENDING_MANAGED_VENV_CREATIONS.get(venvPath);
|
|
7789
|
+
if (pendingCreation) {
|
|
7790
|
+
await pendingCreation;
|
|
7791
|
+
}
|
|
7710
7792
|
const { pythonCmd, venvRoot } = useVirtualEnv(workPath, env, systemPython);
|
|
7711
7793
|
if (venvRoot) {
|
|
7712
7794
|
(0, import_build_utils13.debug)(`Using existing virtualenv at ${venvRoot} for multi-service dev`);
|
|
7713
7795
|
return { command: pythonCmd, args: [] };
|
|
7714
7796
|
}
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
pythonVersion: { pythonPath: systemPython },
|
|
7797
|
+
await dedupePendingOperation(
|
|
7798
|
+
PENDING_MANAGED_VENV_CREATIONS,
|
|
7718
7799
|
venvPath,
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7800
|
+
() => ensureVenv({
|
|
7801
|
+
pythonVersion: { pythonPath: systemPython },
|
|
7802
|
+
venvPath,
|
|
7803
|
+
uvPath,
|
|
7804
|
+
quiet: true
|
|
7805
|
+
})
|
|
7806
|
+
);
|
|
7722
7807
|
(0, import_build_utils13.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
|
|
7723
7808
|
const pythonBin = getVenvPythonBin(venvPath);
|
|
7724
7809
|
const binDir = getVenvBinDir(venvPath);
|
|
@@ -7779,7 +7864,8 @@ var startDevServer = async (opts) => {
|
|
|
7779
7864
|
// Other services use handlerFunction as the entrypoint variable name.
|
|
7780
7865
|
varName: service && (0, import_build_utils13.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
|
|
7781
7866
|
} : void 0,
|
|
7782
|
-
service
|
|
7867
|
+
service,
|
|
7868
|
+
opts.repoRootPath
|
|
7783
7869
|
);
|
|
7784
7870
|
let hookResult;
|
|
7785
7871
|
if (detected?.entrypoint) {
|
|
@@ -7893,7 +7979,11 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
7893
7979
|
} else {
|
|
7894
7980
|
console.log(syncMessage);
|
|
7895
7981
|
}
|
|
7896
|
-
await
|
|
7982
|
+
await dedupePendingOperation(
|
|
7983
|
+
PENDING_DEPENDENCY_SYNCS,
|
|
7984
|
+
workPath,
|
|
7985
|
+
() => syncDependencies(devOpts)
|
|
7986
|
+
);
|
|
7897
7987
|
}
|
|
7898
7988
|
await installInjectedDevPackage(
|
|
7899
7989
|
{
|
|
@@ -8587,8 +8677,8 @@ var import_python_analysis9 = require("@vercel/python-analysis");
|
|
|
8587
8677
|
var import_path14 = require("path");
|
|
8588
8678
|
var import_fs14 = __toESM(require("fs"));
|
|
8589
8679
|
var import_build_utils18 = require("@vercel/build-utils");
|
|
8590
|
-
var SUBSCRIBER_NAME_RE = /^[A-Za-z]([A-Za-z0-9_-]*[A-Za-z0-9])?$/;
|
|
8591
8680
|
var MODULE_ATTR_RE = /^([A-Za-z_][\w]*(?:\.[A-Za-z_][\w]*)*):([A-Za-z_][\w]*)$/;
|
|
8681
|
+
var SUBSCRIBER_OUTPUT_DIR = "_py_subscribers";
|
|
8592
8682
|
var TRIGGER_NUMBER_FIELDS = [
|
|
8593
8683
|
{
|
|
8594
8684
|
field: "max_deliveries",
|
|
@@ -8628,6 +8718,12 @@ function safePathSegment(value) {
|
|
|
8628
8718
|
return /[A-Za-z0-9-]/.test(char) ? char : `_${char.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")}`;
|
|
8629
8719
|
}).join("");
|
|
8630
8720
|
}
|
|
8721
|
+
function getSubscriberOutputPath(subscriberName) {
|
|
8722
|
+
return `${SUBSCRIBER_OUTPUT_DIR}/${safePathSegment(subscriberName)}`;
|
|
8723
|
+
}
|
|
8724
|
+
function getSubscriberConsumerName(subscriberName) {
|
|
8725
|
+
return (0, import_build_utils18.sanitizeConsumerName)(getSubscriberOutputPath(subscriberName));
|
|
8726
|
+
}
|
|
8631
8727
|
async function getPyprojectSubscribers(workPath) {
|
|
8632
8728
|
const pyprojectPath = (0, import_path14.join)(workPath, "pyproject.toml");
|
|
8633
8729
|
if (!import_fs14.default.existsSync(pyprojectPath)) {
|
|
@@ -8638,37 +8734,38 @@ async function getPyprojectSubscribers(workPath) {
|
|
|
8638
8734
|
if (!subscribers) {
|
|
8639
8735
|
return [];
|
|
8640
8736
|
}
|
|
8641
|
-
if (
|
|
8642
|
-
throw subscriberError('"tool.vercel.subscribers" must be an
|
|
8737
|
+
if (!Array.isArray(subscribers)) {
|
|
8738
|
+
throw subscriberError('"tool.vercel.subscribers" must be an array');
|
|
8643
8739
|
}
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
([name, config]) => parseSubscriber(workPath, name, config)
|
|
8647
|
-
)
|
|
8740
|
+
const parsedSubscribers = await Promise.all(
|
|
8741
|
+
subscribers.map((config, index) => parseSubscriber(workPath, index, config))
|
|
8648
8742
|
);
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8743
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
8744
|
+
for (const subscriber of parsedSubscribers) {
|
|
8745
|
+
if (seenNames.has(subscriber.name)) {
|
|
8746
|
+
throw subscriberError(
|
|
8747
|
+
`subscriber "${subscriber.name}" is declared more than once`
|
|
8748
|
+
);
|
|
8749
|
+
}
|
|
8750
|
+
seenNames.add(subscriber.name);
|
|
8655
8751
|
}
|
|
8752
|
+
return parsedSubscribers;
|
|
8753
|
+
}
|
|
8754
|
+
async function parseSubscriber(workPath, index, config) {
|
|
8755
|
+
const label = `subscriber #${index + 1}`;
|
|
8656
8756
|
if (!config || typeof config !== "object" || Array.isArray(config)) {
|
|
8657
|
-
throw subscriberError(
|
|
8757
|
+
throw subscriberError(`${label} must be an object`);
|
|
8658
8758
|
}
|
|
8659
8759
|
for (const key of Object.keys(config)) {
|
|
8660
8760
|
if (!SUBSCRIBER_FIELD_NAMES.has(key)) {
|
|
8661
|
-
throw subscriberError(
|
|
8662
|
-
`subscriber "${name}" has unrecognized field "${key}"`
|
|
8663
|
-
);
|
|
8761
|
+
throw subscriberError(`${label} has unrecognized field "${key}"`);
|
|
8664
8762
|
}
|
|
8665
8763
|
}
|
|
8666
8764
|
if (typeof config.entrypoint !== "string") {
|
|
8667
|
-
throw subscriberError(
|
|
8668
|
-
`subscriber "${name}" must define string field "entrypoint"`
|
|
8669
|
-
);
|
|
8765
|
+
throw subscriberError(`${label} must define string field "entrypoint"`);
|
|
8670
8766
|
}
|
|
8671
|
-
const entrypoint = parseEntrypoint(
|
|
8767
|
+
const entrypoint = parseEntrypoint(label, config.entrypoint);
|
|
8768
|
+
const name = getSubscriberName(entrypoint);
|
|
8672
8769
|
const existingEntrypoint = await resolveExistingEntrypoint(
|
|
8673
8770
|
workPath,
|
|
8674
8771
|
entrypoint.filePath
|
|
@@ -8687,6 +8784,12 @@ async function parseSubscriber(workPath, name, config) {
|
|
|
8687
8784
|
triggerDefaults: parseTriggerDefaults(name, config)
|
|
8688
8785
|
};
|
|
8689
8786
|
}
|
|
8787
|
+
function getSubscriberName({
|
|
8788
|
+
moduleName,
|
|
8789
|
+
variableName
|
|
8790
|
+
}) {
|
|
8791
|
+
return `${moduleName.replace(/\./g, "-")}_${variableName}`;
|
|
8792
|
+
}
|
|
8690
8793
|
function parseEntrypoint(name, value) {
|
|
8691
8794
|
const match = MODULE_ATTR_RE.exec(value);
|
|
8692
8795
|
if (!match) {
|
|
@@ -8755,6 +8858,40 @@ function subscriberError(message) {
|
|
|
8755
8858
|
var writeFile = import_fs15.default.promises.writeFile;
|
|
8756
8859
|
var PYTHON_ENTRYPOINT_DOCS_URL2 = "https://vercel.com/docs/functions/runtimes/python#python-entrypoints";
|
|
8757
8860
|
var version = -1;
|
|
8861
|
+
function getDevSubscriberTopics(subscriber) {
|
|
8862
|
+
const { retryAfterSeconds, initialDelaySeconds } = subscriber.triggerDefaults;
|
|
8863
|
+
return subscriber.topics.map((topic) => ({
|
|
8864
|
+
topic,
|
|
8865
|
+
...retryAfterSeconds === void 0 ? {} : { retryAfterSeconds },
|
|
8866
|
+
...initialDelaySeconds === void 0 ? {} : { initialDelaySeconds }
|
|
8867
|
+
}));
|
|
8868
|
+
}
|
|
8869
|
+
async function getDevSidecars({
|
|
8870
|
+
workPath,
|
|
8871
|
+
build: build2
|
|
8872
|
+
}) {
|
|
8873
|
+
const framework = build2.config?.framework;
|
|
8874
|
+
if (build2.config?.middleware === true || typeof framework !== "string" || !(0, import_build_utils19.isPythonFramework)(framework)) {
|
|
8875
|
+
return [];
|
|
8876
|
+
}
|
|
8877
|
+
const subscribers = await getPyprojectSubscribers(workPath);
|
|
8878
|
+
return subscribers.map((subscriber) => ({
|
|
8879
|
+
type: "subscriber",
|
|
8880
|
+
name: subscriber.name,
|
|
8881
|
+
consumer: getSubscriberConsumerName(subscriber.name),
|
|
8882
|
+
workspace: ".",
|
|
8883
|
+
framework,
|
|
8884
|
+
runtime: "python",
|
|
8885
|
+
builder: {
|
|
8886
|
+
use: build2.use,
|
|
8887
|
+
src: subscriber.entrypoint,
|
|
8888
|
+
config: {
|
|
8889
|
+
handlerFunction: subscriber.variableName
|
|
8890
|
+
}
|
|
8891
|
+
},
|
|
8892
|
+
topics: getDevSubscriberTopics(subscriber)
|
|
8893
|
+
}));
|
|
8894
|
+
}
|
|
8758
8895
|
function addFiles(target, source) {
|
|
8759
8896
|
for (const [p, f] of Object.entries(source)) {
|
|
8760
8897
|
target[p] = f;
|
|
@@ -9052,7 +9189,6 @@ var build = async ({
|
|
|
9052
9189
|
let spawnEnv;
|
|
9053
9190
|
let projectInstallCommand;
|
|
9054
9191
|
let hasCustomCommand = false;
|
|
9055
|
-
let hasCustomBuildCommand = false;
|
|
9056
9192
|
const target = getTargetPlatform(meta.isDev ?? false);
|
|
9057
9193
|
(0, import_build_utils19.debug)(`workPath: ${workPath}`);
|
|
9058
9194
|
workPath = await downloadFilesInWorkPath({
|
|
@@ -9085,7 +9221,8 @@ var build = async ({
|
|
|
9085
9221
|
// For other services, handlerFunction is used as the entrypoint variable name.
|
|
9086
9222
|
varName: service && (0, import_build_utils19.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
|
|
9087
9223
|
} : void 0,
|
|
9088
|
-
service
|
|
9224
|
+
service,
|
|
9225
|
+
repoRootPath
|
|
9089
9226
|
) ?? void 0;
|
|
9090
9227
|
if (detected?.error && detected?.baseDir === void 0) {
|
|
9091
9228
|
throw detected?.error;
|
|
@@ -9258,16 +9395,12 @@ var build = async ({
|
|
|
9258
9395
|
env: pythonEnv,
|
|
9259
9396
|
cwd: workPath
|
|
9260
9397
|
});
|
|
9261
|
-
hasCustomBuildCommand = true;
|
|
9262
9398
|
} else {
|
|
9263
|
-
|
|
9399
|
+
await runPyprojectScript(
|
|
9264
9400
|
workPath,
|
|
9265
9401
|
["vercel-build", "now-build", "build"],
|
|
9266
9402
|
pythonEnv
|
|
9267
9403
|
);
|
|
9268
|
-
if (ranBuildScript) {
|
|
9269
|
-
hasCustomBuildCommand = true;
|
|
9270
|
-
}
|
|
9271
9404
|
}
|
|
9272
9405
|
});
|
|
9273
9406
|
}
|
|
@@ -9371,10 +9504,12 @@ var build = async ({
|
|
|
9371
9504
|
variableName,
|
|
9372
9505
|
extraEnv: extraTrampolineEnv
|
|
9373
9506
|
});
|
|
9374
|
-
const
|
|
9507
|
+
const compileAllEnabled = shouldCompileAll({
|
|
9375
9508
|
isDev: meta.isDev,
|
|
9376
9509
|
hasCustomCommand,
|
|
9377
|
-
|
|
9510
|
+
// A pre-deploy command can rewrite source after the build, which would make
|
|
9511
|
+
// unchecked-hash precompiled bytecode stale; skip precompilation to avoid serving it.
|
|
9512
|
+
hasPreDeployCommand: typeof preDeployCommand === "string"
|
|
9378
9513
|
});
|
|
9379
9514
|
const predefinedExcludes = [
|
|
9380
9515
|
".git/**",
|
|
@@ -9443,55 +9578,63 @@ var build = async ({
|
|
|
9443
9578
|
});
|
|
9444
9579
|
}
|
|
9445
9580
|
});
|
|
9446
|
-
const runCompileAllAndFillBytecode = async () => {
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9581
|
+
const runCompileAllAndFillBytecode = async (capacityBytes) => {
|
|
9582
|
+
try {
|
|
9583
|
+
await builderSpan.child("vc.builder.python.compileall").trace(async (compileSpan) => {
|
|
9584
|
+
const sitePackageDirs = (await getVenvSitePackagesDirs(venvPath)).filter((d) => import_fs15.default.existsSync(d));
|
|
9585
|
+
const pythonBin = getVenvPythonBin(venvPath);
|
|
9586
|
+
console.log("Compiling Python bytecode...");
|
|
9587
|
+
await runCompileAll({
|
|
9588
|
+
pythonBin,
|
|
9589
|
+
filesOrDirectories: [workPath],
|
|
9590
|
+
env: pythonEnv,
|
|
9591
|
+
excludeRegex: getCompileAllAppExcludeRegex(workPath)
|
|
9592
|
+
});
|
|
9593
|
+
await runCompileAll({
|
|
9594
|
+
pythonBin,
|
|
9595
|
+
filesOrDirectories: sitePackageDirs,
|
|
9596
|
+
env: pythonEnv
|
|
9597
|
+
});
|
|
9598
|
+
compileSpan.setAttributes({
|
|
9599
|
+
"python.compileall.enabled": "true",
|
|
9600
|
+
"python.compileall.sitePackageDirectoryCount": String(
|
|
9601
|
+
sitePackageDirs.length
|
|
9602
|
+
)
|
|
9603
|
+
});
|
|
9468
9604
|
});
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
|
|
9605
|
+
const currentSize = await calculateBundleSize(files);
|
|
9606
|
+
let remainingCapacity = capacityBytes - currentSize;
|
|
9607
|
+
if (pythonVersion.major != null && pythonVersion.minor != null) {
|
|
9608
|
+
const appBytecodeInfo = await collectAppBytecodeFiles({
|
|
9609
|
+
workPath,
|
|
9610
|
+
files,
|
|
9611
|
+
pythonMajor: pythonVersion.major,
|
|
9612
|
+
pythonMinor: pythonVersion.minor
|
|
9613
|
+
});
|
|
9614
|
+
remainingCapacity = addBytecodeWithinCapacity(
|
|
9615
|
+
files,
|
|
9616
|
+
appBytecodeInfo,
|
|
9617
|
+
remainingCapacity
|
|
9618
|
+
);
|
|
9619
|
+
}
|
|
9620
|
+
const vendorBytecodeInfo = await depExternalizer.collectBytecodeFiles(
|
|
9621
|
+
{
|
|
9622
|
+
vendorDirName: vendorDir
|
|
9623
|
+
}
|
|
9624
|
+
);
|
|
9625
|
+
await addVendorBytecodeWithinCapacity({
|
|
9475
9626
|
files,
|
|
9476
|
-
|
|
9477
|
-
|
|
9627
|
+
depExternalizer,
|
|
9628
|
+
vendorDir,
|
|
9629
|
+
bytecodeInfo: vendorBytecodeInfo,
|
|
9630
|
+
capacity: remainingCapacity
|
|
9478
9631
|
});
|
|
9479
|
-
|
|
9480
|
-
|
|
9481
|
-
|
|
9482
|
-
remainingCapacity
|
|
9632
|
+
} catch (err) {
|
|
9633
|
+
console.log(
|
|
9634
|
+
"Bytecode precompilation failed; continuing without precompiled bytecode."
|
|
9483
9635
|
);
|
|
9636
|
+
(0, import_build_utils19.debug)(`bytecode precompilation error details: ${err}`);
|
|
9484
9637
|
}
|
|
9485
|
-
const vendorBytecodeInfo = await depExternalizer.collectBytecodeFiles({
|
|
9486
|
-
vendorDirName: vendorDir
|
|
9487
|
-
});
|
|
9488
|
-
await addVendorBytecodeWithinCapacity({
|
|
9489
|
-
files,
|
|
9490
|
-
depExternalizer,
|
|
9491
|
-
vendorDir,
|
|
9492
|
-
bytecodeInfo: vendorBytecodeInfo,
|
|
9493
|
-
capacity: remainingCapacity
|
|
9494
|
-
});
|
|
9495
9638
|
};
|
|
9496
9639
|
const announceLargeFunction = () => console.log(
|
|
9497
9640
|
`Function "${entrypoint}" exceeds the standard size limit; enabling large functions (beta).`
|
|
@@ -9500,17 +9643,29 @@ var build = async ({
|
|
|
9500
9643
|
const { fellBackToFullBundle } = await depExternalizer.generateBundle(files);
|
|
9501
9644
|
if (fellBackToFullBundle) {
|
|
9502
9645
|
announceLargeFunction();
|
|
9503
|
-
if (
|
|
9504
|
-
await runCompileAllAndFillBytecode(
|
|
9646
|
+
if (compileAllEnabled) {
|
|
9647
|
+
await runCompileAllAndFillBytecode(
|
|
9648
|
+
MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE
|
|
9649
|
+
);
|
|
9505
9650
|
}
|
|
9506
9651
|
}
|
|
9507
9652
|
} else {
|
|
9508
9653
|
addFiles(files, depAnalysis.allVendorFiles);
|
|
9509
|
-
if (
|
|
9510
|
-
|
|
9511
|
-
|
|
9512
|
-
|
|
9513
|
-
|
|
9654
|
+
if (depAnalysis.totalBundleSize > LAMBDA_SIZE_THRESHOLD_BYTES) {
|
|
9655
|
+
if (isLargeFunctionsEnabled()) {
|
|
9656
|
+
announceLargeFunction();
|
|
9657
|
+
}
|
|
9658
|
+
if (compileAllEnabled) {
|
|
9659
|
+
await runCompileAllAndFillBytecode(
|
|
9660
|
+
MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE
|
|
9661
|
+
);
|
|
9662
|
+
}
|
|
9663
|
+
} else if (compileAllEnabled) {
|
|
9664
|
+
const capacity = BYTECODE_FILL_CEILING_BYTES - depAnalysis.totalBundleSize;
|
|
9665
|
+
const estimate = await estimateBytecodeSize(files);
|
|
9666
|
+
if (capacity >= BYTECODE_COVERAGE_FLOOR * estimate) {
|
|
9667
|
+
await runCompileAllAndFillBytecode(BYTECODE_FILL_CEILING_BYTES);
|
|
9668
|
+
}
|
|
9514
9669
|
}
|
|
9515
9670
|
}
|
|
9516
9671
|
});
|
|
@@ -9533,9 +9688,8 @@ var build = async ({
|
|
|
9533
9688
|
});
|
|
9534
9689
|
const subscriberLambdas = {};
|
|
9535
9690
|
for (const subscriber of subscribers) {
|
|
9536
|
-
const
|
|
9537
|
-
const
|
|
9538
|
-
const consumer = (0, import_build_utils19.sanitizeConsumerName)(outputPath);
|
|
9691
|
+
const outputPath = getSubscriberOutputPath(subscriber.name);
|
|
9692
|
+
const consumer = getSubscriberConsumerName(subscriber.name);
|
|
9539
9693
|
const experimentalTriggers = subscriber.topics.map(
|
|
9540
9694
|
(topic) => ({
|
|
9541
9695
|
type: "queue/v2beta",
|
|
@@ -9562,6 +9716,7 @@ var build = async ({
|
|
|
9562
9716
|
environment: {
|
|
9563
9717
|
...lambdaEnv,
|
|
9564
9718
|
VERCEL_HAS_WORKER_SERVICES: "1",
|
|
9719
|
+
// Compatibility marker consumed by the current Python runtime.
|
|
9565
9720
|
VERCEL_SERVICE_TYPE: "worker"
|
|
9566
9721
|
},
|
|
9567
9722
|
experimentalTriggers,
|
|
@@ -9664,6 +9819,7 @@ function hasProp(obj, key) {
|
|
|
9664
9819
|
detectEntrypoint,
|
|
9665
9820
|
diagnostics,
|
|
9666
9821
|
downloadFilesInWorkPath,
|
|
9822
|
+
getDevSidecars,
|
|
9667
9823
|
installRequirement,
|
|
9668
9824
|
installRequirementsFile,
|
|
9669
9825
|
prepareCache,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/python",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.49.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"vitest": "2.1.4",
|
|
38
38
|
"which": "3.0.0",
|
|
39
39
|
"@vercel/error-utils": "2.2.0",
|
|
40
|
-
"@vercel/build-utils": "13.32.
|
|
40
|
+
"@vercel/build-utils": "13.32.3",
|
|
41
41
|
"@vercel/python-runtime": "0.16.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|