@vercel/python 6.28.0 → 6.29.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 +236 -245
- package/package.json +4 -4
- package/templates/vc_django_settings.py +3 -0
package/dist/index.js
CHANGED
|
@@ -3228,11 +3228,11 @@ var import_fs11 = __toESM(require("fs"));
|
|
|
3228
3228
|
var import_path13 = require("path");
|
|
3229
3229
|
|
|
3230
3230
|
// src/package-versions.ts
|
|
3231
|
-
var VERCEL_RUNTIME_VERSION = "0.
|
|
3231
|
+
var VERCEL_RUNTIME_VERSION = "0.12.0";
|
|
3232
3232
|
var VERCEL_WORKERS_VERSION = "0.0.13";
|
|
3233
3233
|
|
|
3234
3234
|
// src/index.ts
|
|
3235
|
-
var
|
|
3235
|
+
var import_build_utils15 = require("@vercel/build-utils");
|
|
3236
3236
|
|
|
3237
3237
|
// src/install.ts
|
|
3238
3238
|
var import_execa3 = __toESM(require_execa());
|
|
@@ -5004,7 +5004,7 @@ var diagnostics = async ({
|
|
|
5004
5004
|
var import_child_process2 = require("child_process");
|
|
5005
5005
|
var import_fs7 = require("fs");
|
|
5006
5006
|
var import_path9 = require("path");
|
|
5007
|
-
var
|
|
5007
|
+
var import_build_utils10 = require("@vercel/build-utils");
|
|
5008
5008
|
var import_get_port = __toESM(require_get_port());
|
|
5009
5009
|
var import_is_port_reachable = __toESM(require_is_port_reachable());
|
|
5010
5010
|
|
|
@@ -5013,6 +5013,7 @@ var import_fs6 = __toESM(require("fs"));
|
|
|
5013
5013
|
var import_path8 = require("path");
|
|
5014
5014
|
var import_build_utils7 = require("@vercel/build-utils");
|
|
5015
5015
|
var import_build_utils8 = require("@vercel/build-utils");
|
|
5016
|
+
var import_build_utils9 = require("@vercel/build-utils");
|
|
5016
5017
|
var import_python_analysis5 = require("@vercel/python-analysis");
|
|
5017
5018
|
var PYTHON_ENTRYPOINT_FILENAMES = [
|
|
5018
5019
|
"app",
|
|
@@ -5049,7 +5050,7 @@ async function checkEntrypoint(workPath, relPath) {
|
|
|
5049
5050
|
return (0, import_python_analysis5.findAppOrHandler)(content);
|
|
5050
5051
|
}
|
|
5051
5052
|
async function getPyprojectEntrypoint(workPath) {
|
|
5052
|
-
const pyprojectData = await (0,
|
|
5053
|
+
const pyprojectData = await (0, import_build_utils9.readConfigFile)((0, import_path8.join)(workPath, "pyproject.toml"));
|
|
5053
5054
|
if (!pyprojectData)
|
|
5054
5055
|
return null;
|
|
5055
5056
|
const scripts = pyprojectData.project?.scripts;
|
|
@@ -5074,7 +5075,7 @@ async function findValidEntrypoint(workPath, candidates) {
|
|
|
5074
5075
|
for (const candidate of candidates) {
|
|
5075
5076
|
const varName = await checkEntrypoint(workPath, candidate);
|
|
5076
5077
|
if (varName) {
|
|
5077
|
-
(0,
|
|
5078
|
+
(0, import_build_utils8.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
|
|
5078
5079
|
return { entrypoint: candidate, variableName: varName };
|
|
5079
5080
|
}
|
|
5080
5081
|
}
|
|
@@ -5086,7 +5087,7 @@ async function checkDjangoManage(workPath) {
|
|
|
5086
5087
|
const content = await import_fs6.default.promises.readFile(managePath, "utf-8");
|
|
5087
5088
|
if (!content.includes("DJANGO_SETTINGS_MODULE"))
|
|
5088
5089
|
return false;
|
|
5089
|
-
(0,
|
|
5090
|
+
(0, import_build_utils8.debug)(`Found Django manage.py with DJANGO_SETTINGS_MODULE at ${workPath}`);
|
|
5090
5091
|
return true;
|
|
5091
5092
|
} catch {
|
|
5092
5093
|
return false;
|
|
@@ -5102,55 +5103,78 @@ async function getSubdirectories(workPath) {
|
|
|
5102
5103
|
return [];
|
|
5103
5104
|
}
|
|
5104
5105
|
}
|
|
5105
|
-
|
|
5106
|
-
const
|
|
5106
|
+
function makeDetectError(framework) {
|
|
5107
|
+
const searchedList = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
5108
|
+
return new import_build_utils7.NowBuildError({
|
|
5109
|
+
code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
|
|
5110
|
+
message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
|
|
5111
|
+
link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
|
|
5112
|
+
action: "Learn More"
|
|
5113
|
+
});
|
|
5114
|
+
}
|
|
5115
|
+
async function detectGenericPythonEntrypoint(workPath) {
|
|
5107
5116
|
try {
|
|
5108
|
-
const varName = await checkEntrypoint(workPath, entry);
|
|
5109
|
-
if (varName) {
|
|
5110
|
-
(0, import_build_utils7.debug)(`Using configured Python entrypoint: ${entry}`);
|
|
5111
|
-
return { entrypoint: { entrypoint: entry, variableName: varName } };
|
|
5112
|
-
}
|
|
5113
5117
|
const found = await findValidEntrypoint(
|
|
5114
5118
|
workPath,
|
|
5115
5119
|
PYTHON_CANDIDATE_ENTRYPOINTS
|
|
5116
5120
|
);
|
|
5117
5121
|
return found ? { entrypoint: found } : null;
|
|
5118
5122
|
} catch {
|
|
5119
|
-
(0,
|
|
5123
|
+
(0, import_build_utils8.debug)("Failed to discover Python entrypoint");
|
|
5120
5124
|
return null;
|
|
5121
5125
|
}
|
|
5122
5126
|
}
|
|
5123
|
-
async function detectDjangoPythonEntrypoint(workPath
|
|
5124
|
-
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
5127
|
+
async function detectDjangoPythonEntrypoint(workPath) {
|
|
5125
5128
|
try {
|
|
5126
|
-
const varName = await checkEntrypoint(workPath, entry);
|
|
5127
|
-
if (varName) {
|
|
5128
|
-
(0, import_build_utils7.debug)(`Using configured Python entrypoint: ${entry}`);
|
|
5129
|
-
return { entrypoint: { entrypoint: entry, variableName: varName } };
|
|
5130
|
-
}
|
|
5131
5129
|
const subdirs = await getSubdirectories(workPath);
|
|
5132
5130
|
const rootDirs = ["", ...subdirs];
|
|
5133
5131
|
for (const rootDir of rootDirs) {
|
|
5134
5132
|
const currPath = (0, import_path8.join)(workPath, rootDir);
|
|
5135
5133
|
const isDjango = await checkDjangoManage(currPath);
|
|
5136
5134
|
if (isDjango) {
|
|
5137
|
-
return { baseDir: rootDir };
|
|
5135
|
+
return { baseDir: rootDir, error: makeDetectError("django") };
|
|
5138
5136
|
}
|
|
5139
5137
|
}
|
|
5140
5138
|
const candidates = getCandidateEntrypointsInDirs(rootDirs);
|
|
5141
5139
|
const found = await findValidEntrypoint(workPath, candidates);
|
|
5142
5140
|
return found ? { entrypoint: found } : null;
|
|
5143
5141
|
} catch {
|
|
5144
|
-
(0,
|
|
5142
|
+
(0, import_build_utils8.debug)("Failed to discover Django Python entrypoint");
|
|
5145
5143
|
return null;
|
|
5146
5144
|
}
|
|
5147
5145
|
}
|
|
5148
|
-
async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint) {
|
|
5149
|
-
|
|
5146
|
+
async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint, service) {
|
|
5147
|
+
if (configuredEntrypoint) {
|
|
5148
|
+
const entrypoint = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
5149
|
+
let varName = await checkEntrypoint(workPath, entrypoint);
|
|
5150
|
+
if (!varName) {
|
|
5151
|
+
const isSpecialService = service?.type === "cron" || service?.type === "worker";
|
|
5152
|
+
if (isSpecialService) {
|
|
5153
|
+
varName = "app";
|
|
5154
|
+
}
|
|
5155
|
+
}
|
|
5156
|
+
if (varName) {
|
|
5157
|
+
(0, import_build_utils8.debug)(`Using configured Python entrypoint: ${entrypoint}`);
|
|
5158
|
+
return { entrypoint: { entrypoint, variableName: varName } };
|
|
5159
|
+
} else {
|
|
5160
|
+
return {
|
|
5161
|
+
error: new import_build_utils7.NowBuildError({
|
|
5162
|
+
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
5163
|
+
message: `Could not find a top-level "app", "application", or "handler" in "${entrypoint}".`,
|
|
5164
|
+
link: "https://vercel.com/docs/functions/serverless-functions/runtimes/python",
|
|
5165
|
+
action: "Learn More"
|
|
5166
|
+
})
|
|
5167
|
+
};
|
|
5168
|
+
}
|
|
5169
|
+
}
|
|
5170
|
+
if (!framework) {
|
|
5171
|
+
return null;
|
|
5172
|
+
}
|
|
5173
|
+
const result = framework === "django" ? await detectDjangoPythonEntrypoint(workPath) : await detectGenericPythonEntrypoint(workPath);
|
|
5150
5174
|
if (result)
|
|
5151
5175
|
return result;
|
|
5152
5176
|
const pyprojectEntry = await getPyprojectEntrypoint(workPath);
|
|
5153
|
-
return pyprojectEntry ? { entrypoint: pyprojectEntry } :
|
|
5177
|
+
return pyprojectEntry ? { entrypoint: pyprojectEntry } : { error: makeDetectError(framework) };
|
|
5154
5178
|
}
|
|
5155
5179
|
|
|
5156
5180
|
// src/start-dev-server.ts
|
|
@@ -5240,7 +5264,7 @@ async function syncDependencies({
|
|
|
5240
5264
|
let { manifestPath } = installInfo;
|
|
5241
5265
|
const manifest = pythonPackage.manifest;
|
|
5242
5266
|
if (!manifestType || !manifestPath) {
|
|
5243
|
-
(0,
|
|
5267
|
+
(0, import_build_utils10.debug)("No Python project manifest found, skipping dependency sync");
|
|
5244
5268
|
return;
|
|
5245
5269
|
}
|
|
5246
5270
|
if (manifest?.origin && manifestType === "pyproject.toml") {
|
|
@@ -5250,7 +5274,7 @@ async function syncDependencies({
|
|
|
5250
5274
|
const content = (0, import_python_analysis6.stringifyManifest)(manifest.data);
|
|
5251
5275
|
(0, import_fs7.writeFileSync)(tempPyproject, content, "utf8");
|
|
5252
5276
|
manifestPath = tempPyproject;
|
|
5253
|
-
(0,
|
|
5277
|
+
(0, import_build_utils10.debug)(
|
|
5254
5278
|
`Wrote converted ${manifest.origin.kind} manifest to ${tempPyproject}`
|
|
5255
5279
|
);
|
|
5256
5280
|
}
|
|
@@ -5283,7 +5307,7 @@ async function syncDependencies({
|
|
|
5283
5307
|
for (const [channel, chunk] of captured) {
|
|
5284
5308
|
(channel === "stdout" ? writeOut : writeErr)(chunk.toString());
|
|
5285
5309
|
}
|
|
5286
|
-
throw new
|
|
5310
|
+
throw new import_build_utils10.NowBuildError({
|
|
5287
5311
|
code: "PYTHON_DEPENDENCY_SYNC_FAILED",
|
|
5288
5312
|
message: `Failed to install Python dependencies from ${manifestType}: ${err instanceof Error ? err.message : String(err)}`
|
|
5289
5313
|
});
|
|
@@ -5305,7 +5329,7 @@ async function runSync({
|
|
|
5305
5329
|
switch (manifestType) {
|
|
5306
5330
|
case "uv.lock": {
|
|
5307
5331
|
if (!uvPath) {
|
|
5308
|
-
throw new
|
|
5332
|
+
throw new import_build_utils10.NowBuildError({
|
|
5309
5333
|
code: "PYTHON_DEPENDENCY_SYNC_FAILED",
|
|
5310
5334
|
message: "uv is required to install dependencies from uv.lock.",
|
|
5311
5335
|
link: "https://docs.astral.sh/uv/getting-started/installation/",
|
|
@@ -5327,11 +5351,11 @@ async function runSync({
|
|
|
5327
5351
|
break;
|
|
5328
5352
|
}
|
|
5329
5353
|
default:
|
|
5330
|
-
(0,
|
|
5354
|
+
(0, import_build_utils10.debug)(`Unknown manifest type: ${manifestType}`);
|
|
5331
5355
|
return;
|
|
5332
5356
|
}
|
|
5333
5357
|
await new Promise((resolve3, reject) => {
|
|
5334
|
-
(0,
|
|
5358
|
+
(0, import_build_utils10.debug)(`Running "${spawnCmd} ${spawnArgs.join(" ")}" in ${projectDir}...`);
|
|
5335
5359
|
const child = (0, import_child_process2.spawn)(spawnCmd, spawnArgs, {
|
|
5336
5360
|
cwd: projectDir,
|
|
5337
5361
|
env: getProtectedUvEnv(env),
|
|
@@ -5418,13 +5442,13 @@ async function doInstallVercelRuntime({
|
|
|
5418
5442
|
`vercel_runtime-${VERCEL_RUNTIME_VERSION}.dist-info`
|
|
5419
5443
|
);
|
|
5420
5444
|
if ((0, import_fs7.existsSync)(distInfo)) {
|
|
5421
|
-
(0,
|
|
5445
|
+
(0, import_build_utils10.debug)(
|
|
5422
5446
|
`vercel-runtime ${VERCEL_RUNTIME_VERSION} already installed, skipping`
|
|
5423
5447
|
);
|
|
5424
5448
|
return;
|
|
5425
5449
|
}
|
|
5426
5450
|
}
|
|
5427
|
-
(0,
|
|
5451
|
+
(0, import_build_utils10.debug)(
|
|
5428
5452
|
`Installing vercel-runtime into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${runtimeDep})`
|
|
5429
5453
|
);
|
|
5430
5454
|
const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
|
|
@@ -5439,14 +5463,14 @@ async function doInstallVercelRuntime({
|
|
|
5439
5463
|
if (onStdout) {
|
|
5440
5464
|
onStdout(data);
|
|
5441
5465
|
} else {
|
|
5442
|
-
(0,
|
|
5466
|
+
(0, import_build_utils10.debug)(data.toString());
|
|
5443
5467
|
}
|
|
5444
5468
|
});
|
|
5445
5469
|
child.stderr?.on("data", (data) => {
|
|
5446
5470
|
if (onStderr) {
|
|
5447
5471
|
onStderr(data);
|
|
5448
5472
|
} else {
|
|
5449
|
-
(0,
|
|
5473
|
+
(0, import_build_utils10.debug)(data.toString());
|
|
5450
5474
|
}
|
|
5451
5475
|
});
|
|
5452
5476
|
child.on("error", reject);
|
|
@@ -5514,13 +5538,13 @@ async function doInstallVercelWorkers({
|
|
|
5514
5538
|
`vercel_workers-${VERCEL_WORKERS_VERSION}.dist-info`
|
|
5515
5539
|
);
|
|
5516
5540
|
if ((0, import_fs7.existsSync)(distInfo)) {
|
|
5517
|
-
(0,
|
|
5541
|
+
(0, import_build_utils10.debug)(
|
|
5518
5542
|
`vercel-workers ${VERCEL_WORKERS_VERSION} already installed, skipping`
|
|
5519
5543
|
);
|
|
5520
5544
|
return;
|
|
5521
5545
|
}
|
|
5522
5546
|
}
|
|
5523
|
-
(0,
|
|
5547
|
+
(0, import_build_utils10.debug)(
|
|
5524
5548
|
`Installing vercel-workers into ${targetDir} (type: ${isLocalDev ? "local" : "pypi"}, source: ${workersDep})`
|
|
5525
5549
|
);
|
|
5526
5550
|
const pip = uvPath ? { cmd: uvPath, prefix: ["pip", "install"] } : { cmd: pythonBin, prefix: ["-m", "pip", "install"] };
|
|
@@ -5535,14 +5559,14 @@ async function doInstallVercelWorkers({
|
|
|
5535
5559
|
if (onStdout) {
|
|
5536
5560
|
onStdout(data);
|
|
5537
5561
|
} else {
|
|
5538
|
-
(0,
|
|
5562
|
+
(0, import_build_utils10.debug)(data.toString());
|
|
5539
5563
|
}
|
|
5540
5564
|
});
|
|
5541
5565
|
child.stderr?.on("data", (data) => {
|
|
5542
5566
|
if (onStderr) {
|
|
5543
5567
|
onStderr(data);
|
|
5544
5568
|
} else {
|
|
5545
|
-
(0,
|
|
5569
|
+
(0, import_build_utils10.debug)(data.toString());
|
|
5546
5570
|
}
|
|
5547
5571
|
});
|
|
5548
5572
|
child.on("error", reject);
|
|
@@ -5572,12 +5596,12 @@ function installGlobalCleanupHandlers() {
|
|
|
5572
5596
|
try {
|
|
5573
5597
|
process.kill(info.pid, "SIGTERM");
|
|
5574
5598
|
} catch (err) {
|
|
5575
|
-
(0,
|
|
5599
|
+
(0, import_build_utils10.debug)(`Error sending SIGTERM to ${info.pid}: ${err}`);
|
|
5576
5600
|
}
|
|
5577
5601
|
try {
|
|
5578
5602
|
process.kill(info.pid, "SIGKILL");
|
|
5579
5603
|
} catch (err) {
|
|
5580
|
-
(0,
|
|
5604
|
+
(0, import_build_utils10.debug)(`Error sending SIGKILL to ${info.pid}: ${err}`);
|
|
5581
5605
|
}
|
|
5582
5606
|
PERSISTENT_SERVERS.delete(key);
|
|
5583
5607
|
}
|
|
@@ -5585,7 +5609,7 @@ function installGlobalCleanupHandlers() {
|
|
|
5585
5609
|
try {
|
|
5586
5610
|
restoreWarnings();
|
|
5587
5611
|
} catch (err) {
|
|
5588
|
-
(0,
|
|
5612
|
+
(0, import_build_utils10.debug)(`Error restoring warnings: ${err}`);
|
|
5589
5613
|
}
|
|
5590
5614
|
restoreWarnings = null;
|
|
5591
5615
|
}
|
|
@@ -5622,26 +5646,26 @@ function createDevShim(workPath, entry, modulePath, serviceName, framework, vari
|
|
|
5622
5646
|
const template = (0, import_fs7.readFileSync)(templatePath, "utf8");
|
|
5623
5647
|
const shimSource = template.replace(/__VC_DEV_MODULE_NAME__/g, qualifiedModule).replace(/__VC_DEV_ENTRY_ABS__/g, entryAbs).replace(/__VC_DEV_FRAMEWORK__/g, framework).replace(/__VC_DEV_VARIABLE_NAME__/g, variableName);
|
|
5624
5648
|
(0, import_fs7.writeFileSync)(shimPath, shimSource, "utf8");
|
|
5625
|
-
(0,
|
|
5649
|
+
(0, import_build_utils10.debug)(`Prepared Python dev shim at ${shimPath}`);
|
|
5626
5650
|
return {
|
|
5627
5651
|
module: DEV_SHIM_MODULE,
|
|
5628
5652
|
extraPythonPath,
|
|
5629
5653
|
shimDir: vercelPythonDir
|
|
5630
5654
|
};
|
|
5631
5655
|
} catch (err) {
|
|
5632
|
-
(0,
|
|
5656
|
+
(0, import_build_utils10.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
|
|
5633
5657
|
return null;
|
|
5634
5658
|
}
|
|
5635
5659
|
}
|
|
5636
5660
|
async function getMultiServicePythonRunner(workPath, env, systemPython, uvPath) {
|
|
5637
5661
|
const { pythonCmd, venvRoot } = useVirtualEnv(workPath, env, systemPython);
|
|
5638
5662
|
if (venvRoot) {
|
|
5639
|
-
(0,
|
|
5663
|
+
(0, import_build_utils10.debug)(`Using existing virtualenv at ${venvRoot} for multi-service dev`);
|
|
5640
5664
|
return { command: pythonCmd, args: [] };
|
|
5641
5665
|
}
|
|
5642
5666
|
const venvPath = (0, import_path9.join)(workPath, ".venv");
|
|
5643
5667
|
await ensureVenv({ pythonPath: systemPython, venvPath, uvPath, quiet: true });
|
|
5644
|
-
(0,
|
|
5668
|
+
(0, import_build_utils10.debug)(`Created virtualenv at ${venvPath} for multi-service dev`);
|
|
5645
5669
|
const pythonBin = getVenvPythonBin(venvPath);
|
|
5646
5670
|
const binDir = getVenvBinDir(venvPath);
|
|
5647
5671
|
env.VIRTUAL_ENV = venvPath;
|
|
@@ -5654,11 +5678,12 @@ var startDevServer = async (opts) => {
|
|
|
5654
5678
|
workPath,
|
|
5655
5679
|
meta = {},
|
|
5656
5680
|
config,
|
|
5681
|
+
service,
|
|
5657
5682
|
onStdout,
|
|
5658
5683
|
onStderr
|
|
5659
5684
|
} = opts;
|
|
5660
5685
|
const framework = config?.framework;
|
|
5661
|
-
const serviceName = typeof meta.serviceName === "string" ? meta.serviceName : void 0;
|
|
5686
|
+
const serviceName = service?.name ?? (typeof meta.serviceName === "string" ? meta.serviceName : void 0);
|
|
5662
5687
|
const serverKey = serviceName ? `${workPath}::${framework}::${serviceName}` : `${workPath}::${framework}`;
|
|
5663
5688
|
const existing = PERSISTENT_SERVERS.get(serverKey);
|
|
5664
5689
|
if (existing) {
|
|
@@ -5688,37 +5713,34 @@ var startDevServer = async (opts) => {
|
|
|
5688
5713
|
restoreWarnings = silenceNodeWarnings();
|
|
5689
5714
|
installGlobalCleanupHandlers();
|
|
5690
5715
|
const env = { ...process.env, ...meta.env || {} };
|
|
5691
|
-
const
|
|
5716
|
+
const entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
|
|
5692
5717
|
let resolved;
|
|
5693
|
-
|
|
5694
|
-
|
|
5718
|
+
const detected = await detectPythonEntrypoint(
|
|
5719
|
+
framework,
|
|
5720
|
+
workPath,
|
|
5721
|
+
entrypoint,
|
|
5722
|
+
service
|
|
5723
|
+
);
|
|
5724
|
+
if (detected?.entrypoint) {
|
|
5725
|
+
resolved = detected.entrypoint;
|
|
5695
5726
|
} else {
|
|
5696
|
-
const
|
|
5697
|
-
|
|
5727
|
+
const hookResult = await runFrameworkHook(framework, {
|
|
5728
|
+
pythonEnv: env,
|
|
5729
|
+
projectDir: (0, import_path9.join)(workPath, detected?.baseDir ?? ""),
|
|
5698
5730
|
workPath,
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
5707
|
-
workPath,
|
|
5708
|
-
entrypoint: rawEntrypoint,
|
|
5709
|
-
detected: detected ?? void 0
|
|
5710
|
-
});
|
|
5711
|
-
resolved = hookResult?.entrypoint;
|
|
5712
|
-
}
|
|
5713
|
-
if (!resolved) {
|
|
5714
|
-
const searched = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
5715
|
-
throw new import_build_utils9.NowBuildError({
|
|
5716
|
-
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
5717
|
-
message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searched}.`,
|
|
5718
|
-
link: `https://vercel.com/docs/frameworks/backend/${framework?.toLowerCase()}#exporting-the-${framework?.toLowerCase()}-application`,
|
|
5719
|
-
action: "Learn More"
|
|
5720
|
-
});
|
|
5731
|
+
entrypoint,
|
|
5732
|
+
detected: detected ?? void 0
|
|
5733
|
+
});
|
|
5734
|
+
resolved = hookResult?.entrypoint;
|
|
5735
|
+
}
|
|
5736
|
+
if (!resolved) {
|
|
5737
|
+
if (detected?.error) {
|
|
5738
|
+
throw detected.error;
|
|
5721
5739
|
}
|
|
5740
|
+
throw new import_build_utils10.NowBuildError({
|
|
5741
|
+
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
5742
|
+
message: "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
5743
|
+
});
|
|
5722
5744
|
}
|
|
5723
5745
|
const { entrypoint: entry, variableName } = resolved;
|
|
5724
5746
|
const modulePath = entry.replace(/\.py$/i, "").replace(/[\\/]/g, ".");
|
|
@@ -5744,7 +5766,7 @@ var startDevServer = async (opts) => {
|
|
|
5744
5766
|
const yellow = "\x1B[33m";
|
|
5745
5767
|
const white = "\x1B[1m";
|
|
5746
5768
|
const reset = "\x1B[0m";
|
|
5747
|
-
throw new
|
|
5769
|
+
throw new import_build_utils10.NowBuildError({
|
|
5748
5770
|
code: "PYTHON_EXTERNAL_VENV_DETECTED",
|
|
5749
5771
|
message: `Detected activated venv at ${yellow}${venv}${reset}, ${white}vercel dev${reset} manages virtual environments automatically.
|
|
5750
5772
|
Run ${white}deactivate${reset} and try again.`
|
|
@@ -5761,11 +5783,11 @@ Run ${white}deactivate${reset} and try again.`
|
|
|
5761
5783
|
);
|
|
5762
5784
|
spawnCommand = runner.command;
|
|
5763
5785
|
spawnArgsPrefix = runner.args;
|
|
5764
|
-
(0,
|
|
5786
|
+
(0, import_build_utils10.debug)(
|
|
5765
5787
|
`Multi-service Python runner: ${spawnCommand} ${spawnArgsPrefix.join(" ")}`
|
|
5766
5788
|
);
|
|
5767
5789
|
} else if (venv) {
|
|
5768
|
-
(0,
|
|
5790
|
+
(0, import_build_utils10.debug)(`Running in virtualenv at ${venv}`);
|
|
5769
5791
|
} else {
|
|
5770
5792
|
const { pythonCmd: venvPythonCmd, venvRoot } = useVirtualEnv(
|
|
5771
5793
|
workPath,
|
|
@@ -5774,9 +5796,9 @@ Run ${white}deactivate${reset} and try again.`
|
|
|
5774
5796
|
);
|
|
5775
5797
|
spawnCommand = venvPythonCmd;
|
|
5776
5798
|
if (venvRoot) {
|
|
5777
|
-
(0,
|
|
5799
|
+
(0, import_build_utils10.debug)(`Using virtualenv at ${venvRoot}`);
|
|
5778
5800
|
} else {
|
|
5779
|
-
(0,
|
|
5801
|
+
(0, import_build_utils10.debug)("No virtualenv found");
|
|
5780
5802
|
try {
|
|
5781
5803
|
const yellow = "\x1B[33m";
|
|
5782
5804
|
const reset = "\x1B[0m";
|
|
@@ -5857,7 +5879,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
5857
5879
|
const moduleToRun = devShim?.module || modulePath;
|
|
5858
5880
|
const pythonArgs = ["-u", "-m", moduleToRun];
|
|
5859
5881
|
const argv = [...spawnArgsPrefix, ...pythonArgs];
|
|
5860
|
-
(0,
|
|
5882
|
+
(0, import_build_utils10.debug)(
|
|
5861
5883
|
`Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
|
|
5862
5884
|
);
|
|
5863
5885
|
if (process.stdout.columns) {
|
|
@@ -5911,7 +5933,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
5911
5933
|
};
|
|
5912
5934
|
|
|
5913
5935
|
// src/quirks/index.ts
|
|
5914
|
-
var
|
|
5936
|
+
var import_build_utils13 = require("@vercel/build-utils");
|
|
5915
5937
|
var import_python_analysis8 = require("@vercel/python-analysis");
|
|
5916
5938
|
|
|
5917
5939
|
// src/quirks/matplotlib.ts
|
|
@@ -5927,7 +5949,7 @@ var matplotlibQuirk = {
|
|
|
5927
5949
|
// src/quirks/litellm.ts
|
|
5928
5950
|
var import_fs8 = __toESM(require("fs"));
|
|
5929
5951
|
var import_path10 = require("path");
|
|
5930
|
-
var
|
|
5952
|
+
var import_build_utils11 = require("@vercel/build-utils");
|
|
5931
5953
|
var LAMBDA_ROOT = "/var/task";
|
|
5932
5954
|
var CONFIG_CANDIDATES = [
|
|
5933
5955
|
"litellm_config.yaml",
|
|
@@ -5962,24 +5984,24 @@ var litellmQuirk = {
|
|
|
5962
5984
|
);
|
|
5963
5985
|
try {
|
|
5964
5986
|
await import_fs8.default.promises.access(schemaPath);
|
|
5965
|
-
(0,
|
|
5987
|
+
(0, import_build_utils11.debug)(`LiteLLM quirk: found schema at ${schemaPath}`);
|
|
5966
5988
|
buildEnv.PRISMA_SCHEMA_PATH = schemaPath;
|
|
5967
5989
|
break;
|
|
5968
5990
|
} catch {
|
|
5969
5991
|
}
|
|
5970
5992
|
}
|
|
5971
5993
|
if (!buildEnv.PRISMA_SCHEMA_PATH) {
|
|
5972
|
-
(0,
|
|
5994
|
+
(0, import_build_utils11.debug)("LiteLLM quirk: schema.prisma not found in any site-packages");
|
|
5973
5995
|
}
|
|
5974
5996
|
if (!process.env.CONFIG_FILE_PATH) {
|
|
5975
5997
|
const configName = await findConfigFile(ctx.workPath);
|
|
5976
5998
|
if (configName) {
|
|
5977
|
-
(0,
|
|
5999
|
+
(0, import_build_utils11.debug)(`LiteLLM quirk: found config at ${configName}`);
|
|
5978
6000
|
buildEnv.CONFIG_FILE_PATH = (0, import_path10.join)(ctx.workPath, configName);
|
|
5979
6001
|
env.CONFIG_FILE_PATH = (0, import_path10.join)(LAMBDA_ROOT, configName);
|
|
5980
6002
|
}
|
|
5981
6003
|
} else {
|
|
5982
|
-
(0,
|
|
6004
|
+
(0, import_build_utils11.debug)(
|
|
5983
6005
|
`LiteLLM quirk: CONFIG_FILE_PATH already set to ${process.env.CONFIG_FILE_PATH}`
|
|
5984
6006
|
);
|
|
5985
6007
|
}
|
|
@@ -5991,7 +6013,7 @@ var litellmQuirk = {
|
|
|
5991
6013
|
var import_fs9 = __toESM(require("fs"));
|
|
5992
6014
|
var import_path11 = require("path");
|
|
5993
6015
|
var import_execa4 = __toESM(require_execa());
|
|
5994
|
-
var
|
|
6016
|
+
var import_build_utils12 = require("@vercel/build-utils");
|
|
5995
6017
|
var import_python_analysis7 = require("@vercel/python-analysis");
|
|
5996
6018
|
function execErrorMessage(err) {
|
|
5997
6019
|
if (err != null && typeof err === "object" && "stderr" in err) {
|
|
@@ -6034,7 +6056,7 @@ async function findUserSchema(workPath) {
|
|
|
6034
6056
|
await import_fs9.default.promises.access(resolved);
|
|
6035
6057
|
return resolved;
|
|
6036
6058
|
} catch {
|
|
6037
|
-
(0,
|
|
6059
|
+
(0, import_build_utils12.debug)(`PRISMA_SCHEMA_PATH=${envPath} not found at ${resolved}`);
|
|
6038
6060
|
return null;
|
|
6039
6061
|
}
|
|
6040
6062
|
}
|
|
@@ -6138,7 +6160,7 @@ var prismaQuirk = {
|
|
|
6138
6160
|
dummySchemaPath,
|
|
6139
6161
|
buildDummySchema(generatedDir)
|
|
6140
6162
|
);
|
|
6141
|
-
(0,
|
|
6163
|
+
(0, import_build_utils12.debug)(`Running prisma generate (dummy) with cache dir: ${cacheDir}`);
|
|
6142
6164
|
try {
|
|
6143
6165
|
const dummyResult = await (0, import_execa4.default)(
|
|
6144
6166
|
pythonPath,
|
|
@@ -6150,11 +6172,11 @@ var prismaQuirk = {
|
|
|
6150
6172
|
}
|
|
6151
6173
|
);
|
|
6152
6174
|
if (dummyResult.stdout)
|
|
6153
|
-
(0,
|
|
6175
|
+
(0, import_build_utils12.debug)(`prisma generate (dummy) stdout: ${dummyResult.stdout}`);
|
|
6154
6176
|
if (dummyResult.stderr)
|
|
6155
|
-
(0,
|
|
6177
|
+
(0, import_build_utils12.debug)(`prisma generate (dummy) stderr: ${dummyResult.stderr}`);
|
|
6156
6178
|
} catch (err) {
|
|
6157
|
-
throw new
|
|
6179
|
+
throw new import_build_utils12.NowBuildError({
|
|
6158
6180
|
code: "PRISMA_GENERATE_FAILED",
|
|
6159
6181
|
message: `Prisma engine download failed during \`prisma generate\`. Check that your prisma version is compatible with this Python version.
|
|
6160
6182
|
` + execErrorMessage(err)
|
|
@@ -6173,22 +6195,22 @@ var prismaQuirk = {
|
|
|
6173
6195
|
const destPath = (0, import_path11.join)(cacheDir, runtimeName);
|
|
6174
6196
|
try {
|
|
6175
6197
|
await import_fs9.default.promises.access(destPath);
|
|
6176
|
-
(0,
|
|
6198
|
+
(0, import_build_utils12.debug)(`Engine binary: ${runtimeName} already exists, skipping`);
|
|
6177
6199
|
} catch {
|
|
6178
|
-
(0,
|
|
6200
|
+
(0, import_build_utils12.debug)(`Engine binary: copying ${entry} -> ${runtimeName}`);
|
|
6179
6201
|
await import_fs9.default.promises.copyFile(srcPath, destPath);
|
|
6180
6202
|
}
|
|
6181
6203
|
engineCopied = true;
|
|
6182
6204
|
}
|
|
6183
6205
|
} catch (err) {
|
|
6184
|
-
throw new
|
|
6206
|
+
throw new import_build_utils12.NowBuildError({
|
|
6185
6207
|
code: "PRISMA_ENGINE_NOT_FOUND",
|
|
6186
6208
|
message: `could not read Prisma engine directory "${nodeModulesDir}". This may indicate an incompatible prisma version.
|
|
6187
6209
|
` + (err instanceof Error ? err.message : String(err))
|
|
6188
6210
|
});
|
|
6189
6211
|
}
|
|
6190
6212
|
if (!engineCopied) {
|
|
6191
|
-
throw new
|
|
6213
|
+
throw new import_build_utils12.NowBuildError({
|
|
6192
6214
|
code: "PRISMA_ENGINE_NOT_FOUND",
|
|
6193
6215
|
message: `could not find engine binary matching "${srcBinaryPrefix}*" in "${nodeModulesDir}". This may indicate an incompatible prisma version or an unsupported platform (${process.arch}).`
|
|
6194
6216
|
});
|
|
@@ -6215,14 +6237,14 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
|
|
|
6215
6237
|
pythonEnv
|
|
6216
6238
|
);
|
|
6217
6239
|
if (clientAlreadyGenerated) {
|
|
6218
|
-
(0,
|
|
6240
|
+
(0, import_build_utils12.debug)(
|
|
6219
6241
|
"Prisma quirk: client already generated, skipping user schema generate"
|
|
6220
6242
|
);
|
|
6221
6243
|
shouldGenerate = false;
|
|
6222
6244
|
}
|
|
6223
6245
|
}
|
|
6224
6246
|
if (shouldGenerate) {
|
|
6225
|
-
(0,
|
|
6247
|
+
(0, import_build_utils12.debug)(`Running prisma generate with user schema: ${userSchema}`);
|
|
6226
6248
|
try {
|
|
6227
6249
|
const userResult = await (0, import_execa4.default)(
|
|
6228
6250
|
pythonPath,
|
|
@@ -6234,11 +6256,11 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
|
|
|
6234
6256
|
}
|
|
6235
6257
|
);
|
|
6236
6258
|
if (userResult.stdout)
|
|
6237
|
-
(0,
|
|
6259
|
+
(0, import_build_utils12.debug)(`prisma generate stdout: ${userResult.stdout}`);
|
|
6238
6260
|
if (userResult.stderr)
|
|
6239
|
-
(0,
|
|
6261
|
+
(0, import_build_utils12.debug)(`prisma generate stderr: ${userResult.stderr}`);
|
|
6240
6262
|
} catch (err) {
|
|
6241
|
-
throw new
|
|
6263
|
+
throw new import_build_utils12.NowBuildError({
|
|
6242
6264
|
code: "PRISMA_GENERATE_FAILED",
|
|
6243
6265
|
message: `\`prisma generate\` failed for schema "${userSchema}".
|
|
6244
6266
|
` + execErrorMessage(err)
|
|
@@ -6254,7 +6276,7 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
|
|
|
6254
6276
|
);
|
|
6255
6277
|
const count = await (0, import_python_analysis7.extendDistRecord)(sitePackages, "prisma", allFiles);
|
|
6256
6278
|
if (count > 0) {
|
|
6257
|
-
(0,
|
|
6279
|
+
(0, import_build_utils12.debug)(`Appended ${count} entries to prisma RECORD`);
|
|
6258
6280
|
}
|
|
6259
6281
|
} catch (err) {
|
|
6260
6282
|
console.warn(
|
|
@@ -6348,13 +6370,13 @@ async function runQuirks(ctx) {
|
|
|
6348
6370
|
(0, import_python_analysis8.normalizePackageName)(quirk.dependency)
|
|
6349
6371
|
);
|
|
6350
6372
|
if (!installed) {
|
|
6351
|
-
(0,
|
|
6373
|
+
(0, import_build_utils13.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
|
|
6352
6374
|
}
|
|
6353
6375
|
return installed;
|
|
6354
6376
|
});
|
|
6355
6377
|
const sorted = toposortQuirks(activated);
|
|
6356
6378
|
for (const quirk of sorted) {
|
|
6357
|
-
(0,
|
|
6379
|
+
(0, import_build_utils13.debug)(`Quirk "${quirk.dependency}": detected, running fix-up`);
|
|
6358
6380
|
const result = await quirk.run(ctx);
|
|
6359
6381
|
if (result.env) {
|
|
6360
6382
|
Object.assign(mergedEnv, result.env);
|
|
@@ -6378,31 +6400,30 @@ async function runQuirks(ctx) {
|
|
|
6378
6400
|
var import_fs10 = __toESM(require("fs"));
|
|
6379
6401
|
var import_path12 = require("path");
|
|
6380
6402
|
var import_execa5 = __toESM(require_execa());
|
|
6381
|
-
var
|
|
6403
|
+
var import_build_utils14 = require("@vercel/build-utils");
|
|
6382
6404
|
var scriptPath = (0, import_path12.join)(__dirname, "..", "templates", "vc_django_settings.py");
|
|
6383
6405
|
var script = import_fs10.default.readFileSync(scriptPath, "utf-8");
|
|
6384
6406
|
async function getDjangoSettings(projectDir, env) {
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
return null;
|
|
6393
|
-
return {
|
|
6394
|
-
settingsModule: parsed.settings_module,
|
|
6395
|
-
djangoSettings: parsed.django_settings
|
|
6396
|
-
};
|
|
6397
|
-
} catch (err) {
|
|
6398
|
-
(0, import_build_utils13.debug)(`Django hook: failed to discover settings from manage.py: ${err}`);
|
|
6399
|
-
return null;
|
|
6407
|
+
const { stdout } = await (0, import_execa5.default)("python", ["-c", script], {
|
|
6408
|
+
env,
|
|
6409
|
+
cwd: projectDir
|
|
6410
|
+
});
|
|
6411
|
+
const parsed = JSON.parse(stdout);
|
|
6412
|
+
if (!parsed) {
|
|
6413
|
+
throw new Error("manage.py did not return any settings");
|
|
6400
6414
|
}
|
|
6415
|
+
return {
|
|
6416
|
+
settingsModule: parsed.settings_module,
|
|
6417
|
+
djangoSettings: parsed.django_settings,
|
|
6418
|
+
djangoVersion: parsed.django_version ?? null
|
|
6419
|
+
};
|
|
6401
6420
|
}
|
|
6402
|
-
async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir, settingsModule, djangoSettings) {
|
|
6421
|
+
async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir, settingsModule, djangoSettings, djangoVersion) {
|
|
6403
6422
|
const pythonPath = getVenvPythonBin(venvPath);
|
|
6404
6423
|
const storages = djangoSettings["STORAGES"];
|
|
6405
|
-
const
|
|
6424
|
+
const useLegacySetting = !djangoVersion || djangoVersion[0] < 5 || djangoVersion[0] === 5 && djangoVersion[1] < 1;
|
|
6425
|
+
const legacyBackend = useLegacySetting ? djangoSettings["STATICFILES_STORAGE"] : void 0;
|
|
6426
|
+
const storageBackend = storages?.staticfiles?.BACKEND ?? legacyBackend ?? "django.contrib.staticfiles.storage.StaticFilesStorage";
|
|
6406
6427
|
const staticUrl = djangoSettings["STATIC_URL"] ?? "/static/";
|
|
6407
6428
|
const staticRoot = djangoSettings["STATIC_ROOT"] != null ? String(djangoSettings["STATIC_ROOT"]) : null;
|
|
6408
6429
|
const whitenoiseUseFinders = djangoSettings["WHITENOISE_USE_FINDERS"] === true;
|
|
@@ -6471,7 +6492,7 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
|
|
|
6471
6492
|
await import_fs10.default.promises.mkdir(resolvedStaticRoot, { recursive: true });
|
|
6472
6493
|
await import_fs10.default.promises.copyFile(manifestSrc, manifestDest);
|
|
6473
6494
|
manifestRelPath = (0, import_path12.relative)(workPath, manifestDest);
|
|
6474
|
-
(0,
|
|
6495
|
+
(0, import_build_utils14.debug)(`Copied staticfiles.json to ${manifestDest} for Lambda bundle`);
|
|
6475
6496
|
}
|
|
6476
6497
|
return {
|
|
6477
6498
|
staticSourceDirs,
|
|
@@ -6498,14 +6519,31 @@ var frameworkHooks = {
|
|
|
6498
6519
|
detected
|
|
6499
6520
|
}) => {
|
|
6500
6521
|
if (detected?.baseDir === void 0) {
|
|
6501
|
-
(0,
|
|
6522
|
+
(0, import_build_utils15.debug)("Django hook: no manage.py detected, skipping");
|
|
6502
6523
|
return;
|
|
6503
6524
|
}
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6525
|
+
let settingsResult;
|
|
6526
|
+
try {
|
|
6527
|
+
settingsResult = await getDjangoSettings(projectDir, pythonEnv);
|
|
6528
|
+
} catch (err) {
|
|
6529
|
+
let detail;
|
|
6530
|
+
if (err?.code === "ENOENT") {
|
|
6531
|
+
detail = `command not found: python
|
|
6532
|
+
Hint: activate a venv or run with \`uv run vercel dev\``;
|
|
6533
|
+
} else {
|
|
6534
|
+
detail = err?.stderr || err?.message || String(err);
|
|
6535
|
+
}
|
|
6536
|
+
throw new import_build_utils15.NowBuildError({
|
|
6537
|
+
code: "DJANGO_SETTINGS_FAILED",
|
|
6538
|
+
message: `Failed to read Django application settings from ${projectDir}/manage.py:
|
|
6539
|
+
${detail}`
|
|
6540
|
+
});
|
|
6541
|
+
}
|
|
6542
|
+
(0, import_build_utils15.debug)(`Django settings: ${JSON.stringify(settingsResult)}`);
|
|
6543
|
+
const { djangoSettings, settingsModule, djangoVersion } = settingsResult;
|
|
6544
|
+
if (djangoVersion) {
|
|
6545
|
+
console.log(`Django ${djangoVersion.join(".")} detected`);
|
|
6546
|
+
}
|
|
6509
6547
|
let resolvedEntrypoint;
|
|
6510
6548
|
const baseDir = detected?.baseDir ?? "";
|
|
6511
6549
|
const asgiApp = djangoSettings["ASGI_APPLICATION"];
|
|
@@ -6514,7 +6552,7 @@ var frameworkHooks = {
|
|
|
6514
6552
|
const variableName = parts.at(-1);
|
|
6515
6553
|
const rel = `${parts.slice(0, -1).join("/")}.py`;
|
|
6516
6554
|
const ep = baseDir ? `${baseDir}/${rel}` : rel;
|
|
6517
|
-
(0,
|
|
6555
|
+
(0, import_build_utils15.debug)(`Django hook: ASGI entrypoint: ${ep} (variable: ${variableName})`);
|
|
6518
6556
|
resolvedEntrypoint = { entrypoint: ep, variableName };
|
|
6519
6557
|
} else {
|
|
6520
6558
|
const wsgiApp = djangoSettings["WSGI_APPLICATION"];
|
|
@@ -6523,7 +6561,7 @@ var frameworkHooks = {
|
|
|
6523
6561
|
const variableName = parts.at(-1);
|
|
6524
6562
|
const rel = `${parts.slice(0, -1).join("/")}.py`;
|
|
6525
6563
|
const ep = baseDir ? `${baseDir}/${rel}` : rel;
|
|
6526
|
-
(0,
|
|
6564
|
+
(0, import_build_utils15.debug)(
|
|
6527
6565
|
`Django hook: WSGI entrypoint: ${ep} (variable: ${variableName})`
|
|
6528
6566
|
);
|
|
6529
6567
|
resolvedEntrypoint = { entrypoint: ep, variableName };
|
|
@@ -6538,7 +6576,8 @@ var frameworkHooks = {
|
|
|
6538
6576
|
pythonEnv,
|
|
6539
6577
|
outputStaticDir,
|
|
6540
6578
|
settingsModule,
|
|
6541
|
-
djangoSettings
|
|
6579
|
+
djangoSettings,
|
|
6580
|
+
djangoVersion
|
|
6542
6581
|
);
|
|
6543
6582
|
}
|
|
6544
6583
|
return { entrypoint: resolvedEntrypoint, djangoStatic };
|
|
@@ -6550,14 +6589,14 @@ async function downloadFilesInWorkPath({
|
|
|
6550
6589
|
files,
|
|
6551
6590
|
meta = {}
|
|
6552
6591
|
}) {
|
|
6553
|
-
(0,
|
|
6554
|
-
let downloadedFiles = await (0,
|
|
6555
|
-
if (meta.isDev) {
|
|
6592
|
+
(0, import_build_utils15.debug)("Downloading user files...");
|
|
6593
|
+
let downloadedFiles = await (0, import_build_utils15.download)(files, workPath, meta);
|
|
6594
|
+
if (meta.isDev && entrypoint) {
|
|
6556
6595
|
const { devCacheDir = (0, import_path13.join)(workPath, ".now", "cache") } = meta;
|
|
6557
6596
|
const cacheKey = (0, import_path13.basename)(entrypoint).replace(/\./g, "_");
|
|
6558
6597
|
const destCache = (0, import_path13.join)(devCacheDir, cacheKey);
|
|
6559
|
-
await (0,
|
|
6560
|
-
downloadedFiles = await (0,
|
|
6598
|
+
await (0, import_build_utils15.download)(downloadedFiles, destCache);
|
|
6599
|
+
downloadedFiles = await (0, import_build_utils15.glob)("**", destCache);
|
|
6561
6600
|
workPath = destCache;
|
|
6562
6601
|
}
|
|
6563
6602
|
return workPath;
|
|
@@ -6566,19 +6605,20 @@ var build = async ({
|
|
|
6566
6605
|
workPath,
|
|
6567
6606
|
repoRootPath,
|
|
6568
6607
|
files: originalFiles,
|
|
6569
|
-
entrypoint,
|
|
6608
|
+
entrypoint: rawEntrypoint,
|
|
6570
6609
|
meta = {},
|
|
6571
6610
|
config,
|
|
6572
6611
|
span: parentSpan,
|
|
6573
6612
|
service
|
|
6574
6613
|
}) => {
|
|
6575
|
-
|
|
6614
|
+
let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
|
|
6615
|
+
const builderSpan = parentSpan ?? new import_build_utils15.Span({ name: "vc.builder" });
|
|
6576
6616
|
const framework = config?.framework;
|
|
6577
6617
|
const shouldInstallVercelWorkers = config?.hasWorkerServices === true;
|
|
6578
6618
|
let spawnEnv;
|
|
6579
6619
|
let projectInstallCommand;
|
|
6580
6620
|
let hasCustomCommand = false;
|
|
6581
|
-
(0,
|
|
6621
|
+
(0, import_build_utils15.debug)(`workPath: ${workPath}`);
|
|
6582
6622
|
workPath = await downloadFilesInWorkPath({
|
|
6583
6623
|
workPath,
|
|
6584
6624
|
files: originalFiles,
|
|
@@ -6594,56 +6634,17 @@ var build = async ({
|
|
|
6594
6634
|
console.log('Failed to create "setup.cfg" file');
|
|
6595
6635
|
throw err;
|
|
6596
6636
|
}
|
|
6597
|
-
let fsFiles = await (0, import_build_utils14.glob)("**", workPath);
|
|
6598
6637
|
let detected;
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
if (detected?.entrypoint) {
|
|
6608
|
-
(0, import_build_utils14.debug)(
|
|
6609
|
-
`Resolved Python entrypoint to "${detected.entrypoint.entrypoint}" (configured "${entrypoint}" not found).`
|
|
6610
|
-
);
|
|
6611
|
-
entrypoint = detected.entrypoint.entrypoint;
|
|
6612
|
-
} else {
|
|
6613
|
-
const searchedList = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
6614
|
-
entrypointNotFound = new import_build_utils14.NowBuildError({
|
|
6615
|
-
code: `${framework.toUpperCase()}_ENTRYPOINT_NOT_FOUND`,
|
|
6616
|
-
message: `No ${framework} entrypoint found. Add an 'app' script in pyproject.toml or define an entrypoint in one of: ${searchedList}.`,
|
|
6617
|
-
link: `https://vercel.com/docs/frameworks/backend/${framework}#exporting-the-${framework}-application`,
|
|
6618
|
-
action: "Learn More"
|
|
6619
|
-
});
|
|
6620
|
-
}
|
|
6621
|
-
}
|
|
6622
|
-
if (!detected?.entrypoint && entrypoint.endsWith(".py") && fsFiles[entrypoint]) {
|
|
6623
|
-
const content = await import_fs11.default.promises.readFile(
|
|
6624
|
-
(0, import_path13.join)(workPath, entrypoint),
|
|
6625
|
-
"utf-8"
|
|
6626
|
-
);
|
|
6627
|
-
let varName = await (0, import_python_analysis9.findAppOrHandler)(content);
|
|
6628
|
-
if (!varName) {
|
|
6629
|
-
const isSpecialService = service?.type === "cron" || service?.type === "worker";
|
|
6630
|
-
if (isSpecialService) {
|
|
6631
|
-
varName = "app";
|
|
6632
|
-
} else if (!varName) {
|
|
6633
|
-
throw new import_build_utils14.NowBuildError({
|
|
6634
|
-
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
6635
|
-
message: `Could not find a top-level "app", "application", or "handler" in "${entrypoint}".`,
|
|
6636
|
-
link: "https://vercel.com/docs/functions/serverless-functions/runtimes/python",
|
|
6637
|
-
action: "Learn More"
|
|
6638
|
-
});
|
|
6639
|
-
}
|
|
6640
|
-
}
|
|
6641
|
-
detected = { entrypoint: { entrypoint, variableName: varName } };
|
|
6642
|
-
}
|
|
6643
|
-
if (entrypointNotFound && detected?.baseDir === void 0) {
|
|
6644
|
-
throw entrypointNotFound;
|
|
6638
|
+
detected = await detectPythonEntrypoint(
|
|
6639
|
+
config.framework,
|
|
6640
|
+
workPath,
|
|
6641
|
+
entrypoint,
|
|
6642
|
+
service
|
|
6643
|
+
) ?? void 0;
|
|
6644
|
+
if (detected?.error && detected?.baseDir === void 0) {
|
|
6645
|
+
throw detected?.error;
|
|
6645
6646
|
}
|
|
6646
|
-
const entryDirectory = detected?.baseDir ?? (0, import_path13.dirname)(entrypoint);
|
|
6647
|
+
const entryDirectory = detected?.baseDir ?? (entrypoint ? (0, import_path13.dirname)(entrypoint) : ".");
|
|
6647
6648
|
const entrypointAbsDir = (0, import_path13.join)(workPath, entryDirectory);
|
|
6648
6649
|
const rootDir = repoRootPath ?? workPath;
|
|
6649
6650
|
const pythonPackage = await builderSpan.child("vc.builder.python.discover").trace(
|
|
@@ -6674,7 +6675,6 @@ var build = async ({
|
|
|
6674
6675
|
`
|
|
6675
6676
|
);
|
|
6676
6677
|
}
|
|
6677
|
-
fsFiles = await (0, import_build_utils14.glob)("**", workPath);
|
|
6678
6678
|
const venvPath = service?.name ? (0, import_path13.join)(workPath, ".vercel", "python", "services", service.name, ".venv") : (0, import_path13.join)(workPath, ".vercel", "python", ".venv");
|
|
6679
6679
|
await builderSpan.child("vc.builder.python.venv").trace(async () => {
|
|
6680
6680
|
await ensureVenv({
|
|
@@ -6682,14 +6682,14 @@ var build = async ({
|
|
|
6682
6682
|
venvPath
|
|
6683
6683
|
});
|
|
6684
6684
|
});
|
|
6685
|
-
if ((0,
|
|
6685
|
+
if ((0, import_build_utils15.isPythonFramework)(framework)) {
|
|
6686
6686
|
const {
|
|
6687
6687
|
cliType,
|
|
6688
6688
|
lockfileVersion,
|
|
6689
6689
|
packageJsonPackageManager,
|
|
6690
6690
|
turboSupportsCorepackHome
|
|
6691
|
-
} = await (0,
|
|
6692
|
-
spawnEnv = (0,
|
|
6691
|
+
} = await (0, import_build_utils15.scanParentDirs)(workPath, true);
|
|
6692
|
+
spawnEnv = (0, import_build_utils15.getEnvForPackageManager)({
|
|
6693
6693
|
cliType,
|
|
6694
6694
|
lockfileVersion,
|
|
6695
6695
|
packageJsonPackageManager,
|
|
@@ -6728,14 +6728,14 @@ var build = async ({
|
|
|
6728
6728
|
let uvLockPath = null;
|
|
6729
6729
|
let uvProjectDir = null;
|
|
6730
6730
|
let projectName;
|
|
6731
|
-
await builderSpan.child(
|
|
6731
|
+
await builderSpan.child(import_build_utils15.BUILDER_INSTALLER_STEP, {
|
|
6732
6732
|
installCommand: projectInstallCommand || void 0
|
|
6733
6733
|
}).trace(async () => {
|
|
6734
6734
|
if (projectInstallCommand) {
|
|
6735
6735
|
console.log(
|
|
6736
6736
|
`Running "install" command: \`${projectInstallCommand}\`...`
|
|
6737
6737
|
);
|
|
6738
|
-
await (0,
|
|
6738
|
+
await (0, import_build_utils15.execCommand)(projectInstallCommand, {
|
|
6739
6739
|
env: pythonEnv,
|
|
6740
6740
|
cwd: workPath
|
|
6741
6741
|
});
|
|
@@ -6775,15 +6775,15 @@ var build = async ({
|
|
|
6775
6775
|
});
|
|
6776
6776
|
}
|
|
6777
6777
|
});
|
|
6778
|
-
if ((0,
|
|
6778
|
+
if ((0, import_build_utils15.isPythonFramework)(framework)) {
|
|
6779
6779
|
const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
|
|
6780
6780
|
config?.buildCommand;
|
|
6781
|
-
await builderSpan.child(
|
|
6781
|
+
await builderSpan.child(import_build_utils15.BUILDER_COMPILE_STEP, {
|
|
6782
6782
|
buildCommand: projectBuildCommand || void 0
|
|
6783
6783
|
}).trace(async () => {
|
|
6784
6784
|
if (projectBuildCommand) {
|
|
6785
6785
|
console.log(`Running "${projectBuildCommand}"`);
|
|
6786
|
-
await (0,
|
|
6786
|
+
await (0, import_build_utils15.execCommand)(projectBuildCommand, {
|
|
6787
6787
|
env: pythonEnv,
|
|
6788
6788
|
cwd: workPath
|
|
6789
6789
|
});
|
|
@@ -6805,16 +6805,19 @@ var build = async ({
|
|
|
6805
6805
|
detected
|
|
6806
6806
|
});
|
|
6807
6807
|
const resolved = hookResult?.entrypoint ?? detected?.entrypoint;
|
|
6808
|
-
if (
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
if (
|
|
6813
|
-
throw
|
|
6808
|
+
if (!resolved && detected?.error) {
|
|
6809
|
+
throw detected?.error;
|
|
6810
|
+
}
|
|
6811
|
+
entrypoint = resolved?.entrypoint;
|
|
6812
|
+
if (!entrypoint) {
|
|
6813
|
+
throw new import_build_utils15.NowBuildError({
|
|
6814
|
+
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
6815
|
+
message: "No Python entrypoint could be detected. Please specify an entrypoint file."
|
|
6816
|
+
});
|
|
6814
6817
|
}
|
|
6815
6818
|
const djangoStatic = hookResult?.djangoStatic ?? null;
|
|
6816
6819
|
const runtimeDep = baseEnv.VERCEL_RUNTIME_PYTHON || `vercel-runtime==${VERCEL_RUNTIME_VERSION}`;
|
|
6817
|
-
(0,
|
|
6820
|
+
(0, import_build_utils15.debug)(`Installing ${runtimeDep}`);
|
|
6818
6821
|
await uv.pip({
|
|
6819
6822
|
venvPath,
|
|
6820
6823
|
projectDir: (0, import_path13.join)(workPath, entryDirectory),
|
|
@@ -6822,7 +6825,7 @@ var build = async ({
|
|
|
6822
6825
|
});
|
|
6823
6826
|
if (shouldInstallVercelWorkers) {
|
|
6824
6827
|
const workersDep = baseEnv.VERCEL_WORKERS_PYTHON || `vercel-workers==${VERCEL_WORKERS_VERSION}`;
|
|
6825
|
-
(0,
|
|
6828
|
+
(0, import_build_utils15.debug)(`Installing ${workersDep}`);
|
|
6826
6829
|
await uv.pip({
|
|
6827
6830
|
venvPath,
|
|
6828
6831
|
projectDir: (0, import_path13.join)(workPath, entryDirectory),
|
|
@@ -6833,7 +6836,7 @@ var build = async ({
|
|
|
6833
6836
|
if (quirksResult.buildEnv) {
|
|
6834
6837
|
Object.assign(pythonEnv, quirksResult.buildEnv);
|
|
6835
6838
|
}
|
|
6836
|
-
(0,
|
|
6839
|
+
(0, import_build_utils15.debug)("Entrypoint is", entrypoint);
|
|
6837
6840
|
const moduleName = entrypoint.replace(/\//g, ".").replace(/\.py$/i, "");
|
|
6838
6841
|
const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
|
|
6839
6842
|
if (handlerFunction) {
|
|
@@ -6841,7 +6844,7 @@ var build = async ({
|
|
|
6841
6844
|
const source = await import_fs11.default.promises.readFile(entrypointPath, "utf-8");
|
|
6842
6845
|
const found = await (0, import_python_analysis9.containsTopLevelCallable)(source, handlerFunction);
|
|
6843
6846
|
if (!found) {
|
|
6844
|
-
throw new
|
|
6847
|
+
throw new import_build_utils15.NowBuildError({
|
|
6845
6848
|
code: "PYTHON_HANDLER_NOT_FOUND",
|
|
6846
6849
|
message: `Handler function "${handlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
|
|
6847
6850
|
});
|
|
@@ -6850,7 +6853,7 @@ var build = async ({
|
|
|
6850
6853
|
const vendorDir = resolveVendorDir();
|
|
6851
6854
|
const suffix = meta.isDev && !entrypoint.endsWith(".py") ? ".py" : "";
|
|
6852
6855
|
const entrypointWithSuffix = `${entrypoint}${suffix}`;
|
|
6853
|
-
(0,
|
|
6856
|
+
(0, import_build_utils15.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
6854
6857
|
const handlerFuncEnvLine = handlerFunction ? `
|
|
6855
6858
|
"__VC_HANDLER_FUNC_NAME": "${handlerFunction}",` : "";
|
|
6856
6859
|
const variableName = resolved?.variableName ?? "";
|
|
@@ -6911,18 +6914,6 @@ from vercel_runtime.vc_init import vc_handler
|
|
|
6911
6914
|
"**/yarn.lock",
|
|
6912
6915
|
"**/package-lock.json"
|
|
6913
6916
|
];
|
|
6914
|
-
if (djangoStatic) {
|
|
6915
|
-
const dirsToExclude = [
|
|
6916
|
-
...djangoStatic.staticSourceDirs,
|
|
6917
|
-
...djangoStatic.staticRoot ? [djangoStatic.staticRoot] : []
|
|
6918
|
-
];
|
|
6919
|
-
for (const absDir of dirsToExclude) {
|
|
6920
|
-
const rel = (0, import_path13.relative)(workPath, absDir);
|
|
6921
|
-
if (!rel.startsWith("..")) {
|
|
6922
|
-
predefinedExcludes.push(`${rel}/**`);
|
|
6923
|
-
}
|
|
6924
|
-
}
|
|
6925
|
-
}
|
|
6926
6917
|
const lambdaEnv = {};
|
|
6927
6918
|
lambdaEnv.PYTHONPATH = vendorDir;
|
|
6928
6919
|
Object.assign(lambdaEnv, quirksResult.env);
|
|
@@ -6933,9 +6924,9 @@ from vercel_runtime.vc_init import vc_handler
|
|
|
6933
6924
|
cwd: workPath,
|
|
6934
6925
|
ignore: config && typeof config.excludeFiles === "string" ? [...predefinedExcludes, config.excludeFiles] : predefinedExcludes
|
|
6935
6926
|
};
|
|
6936
|
-
const files = await (0,
|
|
6927
|
+
const files = await (0, import_build_utils15.glob)("**", globOptions);
|
|
6937
6928
|
if (djangoStatic?.manifestRelPath) {
|
|
6938
|
-
files[djangoStatic.manifestRelPath] = new
|
|
6929
|
+
files[djangoStatic.manifestRelPath] = new import_build_utils15.FileFsRef({
|
|
6939
6930
|
fsPath: (0, import_path13.join)(workPath, djangoStatic.manifestRelPath)
|
|
6940
6931
|
});
|
|
6941
6932
|
}
|
|
@@ -6972,12 +6963,12 @@ from vercel_runtime.vc_init import vc_handler
|
|
|
6972
6963
|
}
|
|
6973
6964
|
});
|
|
6974
6965
|
const handlerPyFilename = "vc__handler__python";
|
|
6975
|
-
files[`${handlerPyFilename}.py`] = new
|
|
6966
|
+
files[`${handlerPyFilename}.py`] = new import_build_utils15.FileBlob({ data: runtimeTrampoline });
|
|
6976
6967
|
if (config.framework === "fasthtml") {
|
|
6977
6968
|
const { SESSKEY = "" } = process.env;
|
|
6978
|
-
files[".sesskey"] = new
|
|
6969
|
+
files[".sesskey"] = new import_build_utils15.FileBlob({ data: `"${SESSKEY}"` });
|
|
6979
6970
|
}
|
|
6980
|
-
const output = new
|
|
6971
|
+
const output = new import_build_utils15.Lambda({
|
|
6981
6972
|
files,
|
|
6982
6973
|
handler: `${handlerPyFilename}.vc_handler`,
|
|
6983
6974
|
runtime: pythonVersion.runtime,
|
|
@@ -6993,33 +6984,33 @@ from vercel_runtime.vc_init import vc_handler
|
|
|
6993
6984
|
uvLockPath
|
|
6994
6985
|
});
|
|
6995
6986
|
} catch (err) {
|
|
6996
|
-
(0,
|
|
6987
|
+
(0, import_build_utils15.debug)(
|
|
6997
6988
|
`Failed to write project manifest: ${err instanceof Error ? err.message : String(err)}`
|
|
6998
6989
|
);
|
|
6999
6990
|
}
|
|
7000
6991
|
}
|
|
7001
|
-
if (
|
|
7002
|
-
|
|
7003
|
-
const staticFiles = await (0, import_build_utils14.glob)("**", { cwd: djangoStatic.cdnOutputDir });
|
|
7004
|
-
return {
|
|
7005
|
-
resultVersion: 2,
|
|
7006
|
-
result: {
|
|
7007
|
-
output: {
|
|
7008
|
-
[lambdaPath]: output,
|
|
7009
|
-
...staticFiles
|
|
7010
|
-
},
|
|
7011
|
-
routes: [
|
|
7012
|
-
{ handle: "filesystem" },
|
|
7013
|
-
{ src: "/(.*)", dest: `/${lambdaPath}` }
|
|
7014
|
-
]
|
|
7015
|
-
}
|
|
7016
|
-
};
|
|
6992
|
+
if (!(0, import_build_utils15.isPythonFramework)(framework)) {
|
|
6993
|
+
return { resultVersion: 3, result: { output } };
|
|
7017
6994
|
}
|
|
7018
|
-
|
|
6995
|
+
const lambdaPath = service?.name ? `_svc/${service.name}/index` : "index";
|
|
6996
|
+
const staticFiles = djangoStatic?.cdnOutputDir ? await (0, import_build_utils15.glob)("**", { cwd: djangoStatic.cdnOutputDir }) : {};
|
|
6997
|
+
return {
|
|
6998
|
+
resultVersion: 2,
|
|
6999
|
+
result: {
|
|
7000
|
+
output: {
|
|
7001
|
+
[lambdaPath]: output,
|
|
7002
|
+
...staticFiles
|
|
7003
|
+
},
|
|
7004
|
+
routes: [
|
|
7005
|
+
{ handle: "filesystem" },
|
|
7006
|
+
{ src: "/(.*)", dest: `/${lambdaPath}` }
|
|
7007
|
+
]
|
|
7008
|
+
}
|
|
7009
|
+
};
|
|
7019
7010
|
};
|
|
7020
7011
|
var shouldServe = (opts) => {
|
|
7021
7012
|
const framework = opts.config.framework;
|
|
7022
|
-
if ((0,
|
|
7013
|
+
if ((0, import_build_utils15.isPythonFramework)(framework)) {
|
|
7023
7014
|
const requestPath = opts.requestPath.replace(/\/$/, "");
|
|
7024
7015
|
if (requestPath.startsWith("api") && opts.hasMatched) {
|
|
7025
7016
|
return false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/python",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.29.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"smol-toml": "1.5.2",
|
|
37
37
|
"vitest": "2.1.4",
|
|
38
38
|
"which": "3.0.0",
|
|
39
|
-
"@vercel/build-utils": "13.
|
|
40
|
-
"@vercel/
|
|
41
|
-
"@vercel/
|
|
39
|
+
"@vercel/build-utils": "13.12.1",
|
|
40
|
+
"@vercel/error-utils": "2.0.3",
|
|
41
|
+
"@vercel/python-runtime": "0.12.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "node ../../utils/build-builder.mjs",
|
|
@@ -33,11 +33,14 @@ else:
|
|
|
33
33
|
|
|
34
34
|
mod = importlib.import_module(settings_module)
|
|
35
35
|
settings = {k: getattr(mod, k) for k in dir(mod) if k.isupper()}
|
|
36
|
+
import django
|
|
37
|
+
|
|
36
38
|
print(
|
|
37
39
|
json.dumps(
|
|
38
40
|
{
|
|
39
41
|
"settings_module": settings_module,
|
|
40
42
|
"django_settings": settings,
|
|
43
|
+
"django_version": django.VERSION[:3],
|
|
41
44
|
},
|
|
42
45
|
default=str,
|
|
43
46
|
)
|