@vercel/python 6.26.0 → 6.28.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 +205 -62
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -3223,11 +3223,12 @@ __export(src_exports, {
|
|
|
3223
3223
|
version: () => version
|
|
3224
3224
|
});
|
|
3225
3225
|
module.exports = __toCommonJS(src_exports);
|
|
3226
|
+
var import_child_process3 = require("child_process");
|
|
3226
3227
|
var import_fs11 = __toESM(require("fs"));
|
|
3227
3228
|
var import_path13 = require("path");
|
|
3228
3229
|
|
|
3229
3230
|
// src/package-versions.ts
|
|
3230
|
-
var VERCEL_RUNTIME_VERSION = "0.
|
|
3231
|
+
var VERCEL_RUNTIME_VERSION = "0.11.0";
|
|
3231
3232
|
var VERCEL_WORKERS_VERSION = "0.0.13";
|
|
3232
3233
|
|
|
3233
3234
|
// src/index.ts
|
|
@@ -3257,7 +3258,7 @@ var import_fs = __toESM(require("fs"));
|
|
|
3257
3258
|
var import_os = __toESM(require("os"));
|
|
3258
3259
|
var import_which = __toESM(require_lib());
|
|
3259
3260
|
var import_build_utils = require("@vercel/build-utils");
|
|
3260
|
-
var UV_VERSION = "0.
|
|
3261
|
+
var UV_VERSION = "0.10.11";
|
|
3261
3262
|
var UV_PYTHON_PATH_PREFIX = "/uv/python/";
|
|
3262
3263
|
var UV_PYTHON_DOWNLOADS_MODE = "automatic";
|
|
3263
3264
|
var isWin = process.platform === "win32";
|
|
@@ -3641,7 +3642,27 @@ function detectPlatform() {
|
|
|
3641
3642
|
osMinor = 17;
|
|
3642
3643
|
}
|
|
3643
3644
|
const libc = libcFamily === detectLibc.MUSL ? "musl" : "gnu";
|
|
3644
|
-
|
|
3645
|
+
const SYS_PLATFORM_MAP = {
|
|
3646
|
+
linux: "linux",
|
|
3647
|
+
win32: "win32",
|
|
3648
|
+
darwin: "darwin"
|
|
3649
|
+
};
|
|
3650
|
+
const sysPlatform = SYS_PLATFORM_MAP[process.platform] || "linux";
|
|
3651
|
+
const OS_MAP = {
|
|
3652
|
+
linux: "linux",
|
|
3653
|
+
win32: "windows",
|
|
3654
|
+
darwin: "macos"
|
|
3655
|
+
};
|
|
3656
|
+
const detectedOs = OS_MAP[process.platform] || "linux";
|
|
3657
|
+
return {
|
|
3658
|
+
osName,
|
|
3659
|
+
archName,
|
|
3660
|
+
osMajor,
|
|
3661
|
+
osMinor,
|
|
3662
|
+
os: detectedOs,
|
|
3663
|
+
sysPlatform,
|
|
3664
|
+
libc
|
|
3665
|
+
};
|
|
3645
3666
|
}
|
|
3646
3667
|
|
|
3647
3668
|
// src/version.ts
|
|
@@ -4499,10 +4520,31 @@ To fix this, either:
|
|
|
4499
4520
|
* Identify public packages that have no compatible wheel for the Lambda platform.
|
|
4500
4521
|
* These packages must be force-bundled because `uv sync --no-build` at cold start
|
|
4501
4522
|
* will refuse to build from source.
|
|
4523
|
+
*
|
|
4524
|
+
* Packages that are not reachable on the target platform (e.g. pywin32 which is
|
|
4525
|
+
* only a dependency when `sys_platform == 'win32'`) are excluded -- they will
|
|
4526
|
+
* never be installed by `uv sync` on Lambda, so their wheel compatibility is
|
|
4527
|
+
* irrelevant.
|
|
4502
4528
|
*/
|
|
4503
4529
|
async findPackagesWithoutCompatibleWheels(lockFile, publicPackageNames) {
|
|
4504
4530
|
const platform = detectPlatform();
|
|
4505
|
-
const
|
|
4531
|
+
const reachable = await getPackagesReachableOnPlatform(
|
|
4532
|
+
lockFile,
|
|
4533
|
+
this.projectName,
|
|
4534
|
+
this.pythonMajor,
|
|
4535
|
+
this.pythonMinor,
|
|
4536
|
+
platform.sysPlatform,
|
|
4537
|
+
platform.archName
|
|
4538
|
+
);
|
|
4539
|
+
const relevantPackages = reachable ? publicPackageNames.filter(
|
|
4540
|
+
(name) => reachable.has((0, import_python_analysis3.normalizePackageName)(name))
|
|
4541
|
+
) : publicPackageNames;
|
|
4542
|
+
if (relevantPackages.length < publicPackageNames.length) {
|
|
4543
|
+
(0, import_build_utils5.debug)(
|
|
4544
|
+
`Skipping wheel check for ${publicPackageNames.length - relevantPackages.length} package(s) not reachable on the target platform`
|
|
4545
|
+
);
|
|
4546
|
+
}
|
|
4547
|
+
const publicSet = new Set(relevantPackages.map(import_python_analysis3.normalizePackageName));
|
|
4506
4548
|
const packageWheels = /* @__PURE__ */ new Map();
|
|
4507
4549
|
for (const pkg of lockFile.packages) {
|
|
4508
4550
|
const normalized = (0, import_python_analysis3.normalizePackageName)(pkg.name);
|
|
@@ -4511,7 +4553,7 @@ To fix this, either:
|
|
|
4511
4553
|
}
|
|
4512
4554
|
}
|
|
4513
4555
|
const incompatible = [];
|
|
4514
|
-
for (const name of
|
|
4556
|
+
for (const name of relevantPackages) {
|
|
4515
4557
|
const normalized = (0, import_python_analysis3.normalizePackageName)(name);
|
|
4516
4558
|
const wheels = packageWheels.get(normalized);
|
|
4517
4559
|
if (!wheels || wheels.length === 0) {
|
|
@@ -4550,6 +4592,64 @@ To fix this, either:
|
|
|
4550
4592
|
return incompatible;
|
|
4551
4593
|
}
|
|
4552
4594
|
};
|
|
4595
|
+
async function getPackagesReachableOnPlatform(lockFile, projectName, pythonMajor, pythonMinor, sysPlatform, platformMachine) {
|
|
4596
|
+
if (!projectName)
|
|
4597
|
+
return null;
|
|
4598
|
+
const rootNormalized = (0, import_python_analysis3.normalizePackageName)(projectName);
|
|
4599
|
+
const packageMap = /* @__PURE__ */ new Map();
|
|
4600
|
+
for (const pkg of lockFile.packages) {
|
|
4601
|
+
packageMap.set((0, import_python_analysis3.normalizePackageName)(pkg.name), pkg);
|
|
4602
|
+
}
|
|
4603
|
+
const rootPkg = packageMap.get(rootNormalized);
|
|
4604
|
+
if (!rootPkg)
|
|
4605
|
+
return null;
|
|
4606
|
+
const visited = /* @__PURE__ */ new Set();
|
|
4607
|
+
const queue = [];
|
|
4608
|
+
let queueHead = 0;
|
|
4609
|
+
async function enqueueDeps(pkg) {
|
|
4610
|
+
if (!pkg.dependencies)
|
|
4611
|
+
return;
|
|
4612
|
+
for (const dep of pkg.dependencies) {
|
|
4613
|
+
const normalized = (0, import_python_analysis3.normalizePackageName)(dep.name);
|
|
4614
|
+
if (visited.has(normalized))
|
|
4615
|
+
continue;
|
|
4616
|
+
if (dep.marker) {
|
|
4617
|
+
try {
|
|
4618
|
+
const compatible = await (0, import_python_analysis3.evaluateMarker)(
|
|
4619
|
+
dep.marker,
|
|
4620
|
+
pythonMajor,
|
|
4621
|
+
pythonMinor,
|
|
4622
|
+
sysPlatform,
|
|
4623
|
+
platformMachine
|
|
4624
|
+
);
|
|
4625
|
+
if (!compatible) {
|
|
4626
|
+
(0, import_build_utils5.debug)(
|
|
4627
|
+
`Skipping dependency ${dep.name}: marker "${dep.marker}" not satisfied on ${sysPlatform}`
|
|
4628
|
+
);
|
|
4629
|
+
continue;
|
|
4630
|
+
}
|
|
4631
|
+
} catch (err) {
|
|
4632
|
+
(0, import_build_utils5.debug)(
|
|
4633
|
+
`Failed to evaluate marker "${dep.marker}" for ${dep.name}, including conservatively: ${err instanceof Error ? err.message : String(err)}`
|
|
4634
|
+
);
|
|
4635
|
+
}
|
|
4636
|
+
}
|
|
4637
|
+
queue.push(normalized);
|
|
4638
|
+
}
|
|
4639
|
+
}
|
|
4640
|
+
await enqueueDeps(rootPkg);
|
|
4641
|
+
while (queueHead < queue.length) {
|
|
4642
|
+
const current = queue[queueHead++];
|
|
4643
|
+
if (visited.has(current))
|
|
4644
|
+
continue;
|
|
4645
|
+
visited.add(current);
|
|
4646
|
+
const pkg = packageMap.get(current);
|
|
4647
|
+
if (pkg) {
|
|
4648
|
+
await enqueueDeps(pkg);
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
return visited;
|
|
4652
|
+
}
|
|
4553
4653
|
async function mirrorPackagesIntoVendor({
|
|
4554
4654
|
venvPath,
|
|
4555
4655
|
vendorDirName,
|
|
@@ -4913,6 +5013,7 @@ var import_fs6 = __toESM(require("fs"));
|
|
|
4913
5013
|
var import_path8 = require("path");
|
|
4914
5014
|
var import_build_utils7 = require("@vercel/build-utils");
|
|
4915
5015
|
var import_build_utils8 = require("@vercel/build-utils");
|
|
5016
|
+
var import_python_analysis5 = require("@vercel/python-analysis");
|
|
4916
5017
|
var PYTHON_ENTRYPOINT_FILENAMES = [
|
|
4917
5018
|
"app",
|
|
4918
5019
|
"index",
|
|
@@ -4943,8 +5044,9 @@ async function fileExists(filePath) {
|
|
|
4943
5044
|
async function checkEntrypoint(workPath, relPath) {
|
|
4944
5045
|
const absPath = (0, import_path8.join)(workPath, relPath);
|
|
4945
5046
|
if (!await fileExists(absPath))
|
|
4946
|
-
return
|
|
4947
|
-
|
|
5047
|
+
return null;
|
|
5048
|
+
const content = await import_fs6.default.promises.readFile(absPath, "utf-8");
|
|
5049
|
+
return (0, import_python_analysis5.findAppOrHandler)(content);
|
|
4948
5050
|
}
|
|
4949
5051
|
async function getPyprojectEntrypoint(workPath) {
|
|
4950
5052
|
const pyprojectData = await (0, import_build_utils8.readConfigFile)((0, import_path8.join)(workPath, "pyproject.toml"));
|
|
@@ -4970,9 +5072,10 @@ async function getPyprojectEntrypoint(workPath) {
|
|
|
4970
5072
|
}
|
|
4971
5073
|
async function findValidEntrypoint(workPath, candidates) {
|
|
4972
5074
|
for (const candidate of candidates) {
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
|
|
5075
|
+
const varName = await checkEntrypoint(workPath, candidate);
|
|
5076
|
+
if (varName) {
|
|
5077
|
+
(0, import_build_utils7.debug)(`Detected Python entrypoint: ${candidate} (variable: ${varName})`);
|
|
5078
|
+
return { entrypoint: candidate, variableName: varName };
|
|
4976
5079
|
}
|
|
4977
5080
|
}
|
|
4978
5081
|
return null;
|
|
@@ -5002,9 +5105,10 @@ async function getSubdirectories(workPath) {
|
|
|
5002
5105
|
async function detectGenericPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
5003
5106
|
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
5004
5107
|
try {
|
|
5005
|
-
|
|
5108
|
+
const varName = await checkEntrypoint(workPath, entry);
|
|
5109
|
+
if (varName) {
|
|
5006
5110
|
(0, import_build_utils7.debug)(`Using configured Python entrypoint: ${entry}`);
|
|
5007
|
-
return { entrypoint: entry };
|
|
5111
|
+
return { entrypoint: { entrypoint: entry, variableName: varName } };
|
|
5008
5112
|
}
|
|
5009
5113
|
const found = await findValidEntrypoint(
|
|
5010
5114
|
workPath,
|
|
@@ -5019,9 +5123,10 @@ async function detectGenericPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
|
5019
5123
|
async function detectDjangoPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
5020
5124
|
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
5021
5125
|
try {
|
|
5022
|
-
|
|
5126
|
+
const varName = await checkEntrypoint(workPath, entry);
|
|
5127
|
+
if (varName) {
|
|
5023
5128
|
(0, import_build_utils7.debug)(`Using configured Python entrypoint: ${entry}`);
|
|
5024
|
-
return { entrypoint: entry };
|
|
5129
|
+
return { entrypoint: { entrypoint: entry, variableName: varName } };
|
|
5025
5130
|
}
|
|
5026
5131
|
const subdirs = await getSubdirectories(workPath);
|
|
5027
5132
|
const rootDirs = ["", ...subdirs];
|
|
@@ -5045,16 +5150,11 @@ async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint)
|
|
|
5045
5150
|
if (result)
|
|
5046
5151
|
return result;
|
|
5047
5152
|
const pyprojectEntry = await getPyprojectEntrypoint(workPath);
|
|
5048
|
-
|
|
5049
|
-
return null;
|
|
5050
|
-
return {
|
|
5051
|
-
entrypoint: pyprojectEntry.entrypoint,
|
|
5052
|
-
variableName: pyprojectEntry.variableName
|
|
5053
|
-
};
|
|
5153
|
+
return pyprojectEntry ? { entrypoint: pyprojectEntry } : null;
|
|
5054
5154
|
}
|
|
5055
5155
|
|
|
5056
5156
|
// src/start-dev-server.ts
|
|
5057
|
-
var
|
|
5157
|
+
var import_python_analysis6 = require("@vercel/python-analysis");
|
|
5058
5158
|
var DEV_SERVER_STARTUP_TIMEOUT = 5 * 6e4;
|
|
5059
5159
|
function silenceNodeWarnings() {
|
|
5060
5160
|
const original = process.emitWarning.bind(
|
|
@@ -5147,7 +5247,7 @@ async function syncDependencies({
|
|
|
5147
5247
|
const syncDir = (0, import_path9.join)(workPath, ".vercel", "python", "sync");
|
|
5148
5248
|
(0, import_fs7.mkdirSync)(syncDir, { recursive: true });
|
|
5149
5249
|
const tempPyproject = (0, import_path9.join)(syncDir, "pyproject.toml");
|
|
5150
|
-
const content = (0,
|
|
5250
|
+
const content = (0, import_python_analysis6.stringifyManifest)(manifest.data);
|
|
5151
5251
|
(0, import_fs7.writeFileSync)(tempPyproject, content, "utf8");
|
|
5152
5252
|
manifestPath = tempPyproject;
|
|
5153
5253
|
(0, import_build_utils9.debug)(
|
|
@@ -5589,19 +5689,18 @@ var startDevServer = async (opts) => {
|
|
|
5589
5689
|
installGlobalCleanupHandlers();
|
|
5590
5690
|
const env = { ...process.env, ...meta.env || {} };
|
|
5591
5691
|
const serviceType = env.VERCEL_SERVICE_TYPE;
|
|
5592
|
-
let
|
|
5593
|
-
let variableName;
|
|
5692
|
+
let resolved;
|
|
5594
5693
|
if ((serviceType === "cron" || serviceType === "worker") && rawEntrypoint?.endsWith(".py")) {
|
|
5595
|
-
|
|
5694
|
+
resolved = { entrypoint: rawEntrypoint, variableName: "app" };
|
|
5596
5695
|
} else {
|
|
5597
5696
|
const detected = await detectPythonEntrypoint(
|
|
5598
5697
|
framework,
|
|
5599
5698
|
workPath,
|
|
5600
5699
|
rawEntrypoint
|
|
5601
5700
|
);
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5701
|
+
if (detected?.entrypoint) {
|
|
5702
|
+
resolved = detected.entrypoint;
|
|
5703
|
+
} else {
|
|
5605
5704
|
const hookResult = await runFrameworkHook(framework, {
|
|
5606
5705
|
pythonEnv: env,
|
|
5607
5706
|
projectDir: (0, import_path9.join)(workPath, detected?.baseDir ?? ""),
|
|
@@ -5609,10 +5708,9 @@ var startDevServer = async (opts) => {
|
|
|
5609
5708
|
entrypoint: rawEntrypoint,
|
|
5610
5709
|
detected: detected ?? void 0
|
|
5611
5710
|
});
|
|
5612
|
-
|
|
5613
|
-
variableName = hookResult?.variableName;
|
|
5711
|
+
resolved = hookResult?.entrypoint;
|
|
5614
5712
|
}
|
|
5615
|
-
if (!
|
|
5713
|
+
if (!resolved) {
|
|
5616
5714
|
const searched = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
5617
5715
|
throw new import_build_utils9.NowBuildError({
|
|
5618
5716
|
code: "PYTHON_ENTRYPOINT_NOT_FOUND",
|
|
@@ -5622,6 +5720,7 @@ var startDevServer = async (opts) => {
|
|
|
5622
5720
|
});
|
|
5623
5721
|
}
|
|
5624
5722
|
}
|
|
5723
|
+
const { entrypoint: entry, variableName } = resolved;
|
|
5625
5724
|
const modulePath = entry.replace(/\.py$/i, "").replace(/[\\/]/g, ".");
|
|
5626
5725
|
let childProcess = null;
|
|
5627
5726
|
let stdoutLogListener = null;
|
|
@@ -5813,7 +5912,7 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
5813
5912
|
|
|
5814
5913
|
// src/quirks/index.ts
|
|
5815
5914
|
var import_build_utils12 = require("@vercel/build-utils");
|
|
5816
|
-
var
|
|
5915
|
+
var import_python_analysis8 = require("@vercel/python-analysis");
|
|
5817
5916
|
|
|
5818
5917
|
// src/quirks/matplotlib.ts
|
|
5819
5918
|
var matplotlibQuirk = {
|
|
@@ -5893,7 +5992,7 @@ var import_fs9 = __toESM(require("fs"));
|
|
|
5893
5992
|
var import_path11 = require("path");
|
|
5894
5993
|
var import_execa4 = __toESM(require_execa());
|
|
5895
5994
|
var import_build_utils11 = require("@vercel/build-utils");
|
|
5896
|
-
var
|
|
5995
|
+
var import_python_analysis7 = require("@vercel/python-analysis");
|
|
5897
5996
|
function execErrorMessage(err) {
|
|
5898
5997
|
if (err != null && typeof err === "object" && "stderr" in err) {
|
|
5899
5998
|
const stderr = String(err.stderr);
|
|
@@ -6153,7 +6252,7 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
|
|
|
6153
6252
|
(0, import_path11.join)(sitePackages, "prisma"),
|
|
6154
6253
|
sitePackages
|
|
6155
6254
|
);
|
|
6156
|
-
const count = await (0,
|
|
6255
|
+
const count = await (0, import_python_analysis7.extendDistRecord)(sitePackages, "prisma", allFiles);
|
|
6157
6256
|
if (count > 0) {
|
|
6158
6257
|
(0, import_build_utils11.debug)(`Appended ${count} entries to prisma RECORD`);
|
|
6159
6258
|
}
|
|
@@ -6178,7 +6277,7 @@ var quirks = [litellmQuirk, prismaQuirk, matplotlibQuirk];
|
|
|
6178
6277
|
function toposortQuirks(activated) {
|
|
6179
6278
|
const nameToQuirk = /* @__PURE__ */ new Map();
|
|
6180
6279
|
for (const q of activated) {
|
|
6181
|
-
nameToQuirk.set((0,
|
|
6280
|
+
nameToQuirk.set((0, import_python_analysis8.normalizePackageName)(q.dependency), q);
|
|
6182
6281
|
}
|
|
6183
6282
|
const adj = /* @__PURE__ */ new Map();
|
|
6184
6283
|
const inDegree = /* @__PURE__ */ new Map();
|
|
@@ -6189,7 +6288,7 @@ function toposortQuirks(activated) {
|
|
|
6189
6288
|
for (const q of activated) {
|
|
6190
6289
|
if (q.runsBefore) {
|
|
6191
6290
|
for (const dep of q.runsBefore) {
|
|
6192
|
-
const target = nameToQuirk.get((0,
|
|
6291
|
+
const target = nameToQuirk.get((0, import_python_analysis8.normalizePackageName)(dep));
|
|
6193
6292
|
if (target) {
|
|
6194
6293
|
adj.get(q).add(target);
|
|
6195
6294
|
inDegree.set(target, inDegree.get(target) + 1);
|
|
@@ -6198,7 +6297,7 @@ function toposortQuirks(activated) {
|
|
|
6198
6297
|
}
|
|
6199
6298
|
if (q.runsAfter) {
|
|
6200
6299
|
for (const dep of q.runsAfter) {
|
|
6201
|
-
const source = nameToQuirk.get((0,
|
|
6300
|
+
const source = nameToQuirk.get((0, import_python_analysis8.normalizePackageName)(dep));
|
|
6202
6301
|
if (source) {
|
|
6203
6302
|
adj.get(source).add(q);
|
|
6204
6303
|
inDegree.set(q, inDegree.get(q) + 1);
|
|
@@ -6239,14 +6338,14 @@ async function runQuirks(ctx) {
|
|
|
6239
6338
|
const installedNames = /* @__PURE__ */ new Set();
|
|
6240
6339
|
const sitePackageDirs = await getVenvSitePackagesDirs(ctx.venvPath);
|
|
6241
6340
|
for (const dir of sitePackageDirs) {
|
|
6242
|
-
const distributions = await (0,
|
|
6341
|
+
const distributions = await (0, import_python_analysis8.scanDistributions)(dir);
|
|
6243
6342
|
for (const name of distributions.keys()) {
|
|
6244
|
-
installedNames.add((0,
|
|
6343
|
+
installedNames.add((0, import_python_analysis8.normalizePackageName)(name));
|
|
6245
6344
|
}
|
|
6246
6345
|
}
|
|
6247
6346
|
const activated = quirks.filter((quirk) => {
|
|
6248
6347
|
const installed = installedNames.has(
|
|
6249
|
-
(0,
|
|
6348
|
+
(0, import_python_analysis8.normalizePackageName)(quirk.dependency)
|
|
6250
6349
|
);
|
|
6251
6350
|
if (!installed) {
|
|
6252
6351
|
(0, import_build_utils12.debug)(`Quirk "${quirk.dependency}": not installed, skipping`);
|
|
@@ -6325,6 +6424,7 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
|
|
|
6325
6424
|
return {
|
|
6326
6425
|
staticSourceDirs,
|
|
6327
6426
|
staticRoot: staticRoot ? (0, import_path12.resolve)(workPath, staticRoot) : null,
|
|
6427
|
+
cdnOutputDir: null,
|
|
6328
6428
|
manifestRelPath: null
|
|
6329
6429
|
};
|
|
6330
6430
|
}
|
|
@@ -6376,14 +6476,15 @@ async function runDjangoCollectStatic(venvPath, workPath, env, outputStaticDir,
|
|
|
6376
6476
|
return {
|
|
6377
6477
|
staticSourceDirs,
|
|
6378
6478
|
staticRoot: staticRoot ? (0, import_path12.resolve)(workPath, staticRoot) : null,
|
|
6479
|
+
cdnOutputDir: outputStaticDir,
|
|
6379
6480
|
manifestRelPath
|
|
6380
6481
|
};
|
|
6381
6482
|
}
|
|
6382
6483
|
|
|
6383
6484
|
// src/index.ts
|
|
6384
|
-
var
|
|
6485
|
+
var import_python_analysis9 = require("@vercel/python-analysis");
|
|
6385
6486
|
var writeFile = import_fs11.default.promises.writeFile;
|
|
6386
|
-
var version =
|
|
6487
|
+
var version = -1;
|
|
6387
6488
|
async function runFrameworkHook(framework, ctx) {
|
|
6388
6489
|
const hook = framework ? frameworkHooks[framework] : void 0;
|
|
6389
6490
|
return hook?.(ctx);
|
|
@@ -6405,28 +6506,27 @@ var frameworkHooks = {
|
|
|
6405
6506
|
if (!settingsResult)
|
|
6406
6507
|
return;
|
|
6407
6508
|
const { djangoSettings, settingsModule } = settingsResult;
|
|
6408
|
-
let
|
|
6409
|
-
let variableName;
|
|
6509
|
+
let resolvedEntrypoint;
|
|
6410
6510
|
const baseDir = detected?.baseDir ?? "";
|
|
6411
6511
|
const asgiApp = djangoSettings["ASGI_APPLICATION"];
|
|
6412
6512
|
if (typeof asgiApp === "string") {
|
|
6413
6513
|
const parts = asgiApp.split(".");
|
|
6414
|
-
variableName = parts.at(-1);
|
|
6514
|
+
const variableName = parts.at(-1);
|
|
6415
6515
|
const rel = `${parts.slice(0, -1).join("/")}.py`;
|
|
6416
|
-
|
|
6417
|
-
(0, import_build_utils14.debug)(
|
|
6418
|
-
|
|
6419
|
-
);
|
|
6516
|
+
const ep = baseDir ? `${baseDir}/${rel}` : rel;
|
|
6517
|
+
(0, import_build_utils14.debug)(`Django hook: ASGI entrypoint: ${ep} (variable: ${variableName})`);
|
|
6518
|
+
resolvedEntrypoint = { entrypoint: ep, variableName };
|
|
6420
6519
|
} else {
|
|
6421
6520
|
const wsgiApp = djangoSettings["WSGI_APPLICATION"];
|
|
6422
6521
|
if (typeof wsgiApp === "string") {
|
|
6423
6522
|
const parts = wsgiApp.split(".");
|
|
6424
|
-
variableName = parts.at(-1);
|
|
6523
|
+
const variableName = parts.at(-1);
|
|
6425
6524
|
const rel = `${parts.slice(0, -1).join("/")}.py`;
|
|
6426
|
-
|
|
6525
|
+
const ep = baseDir ? `${baseDir}/${rel}` : rel;
|
|
6427
6526
|
(0, import_build_utils14.debug)(
|
|
6428
|
-
`Django hook: WSGI entrypoint: ${
|
|
6527
|
+
`Django hook: WSGI entrypoint: ${ep} (variable: ${variableName})`
|
|
6429
6528
|
);
|
|
6529
|
+
resolvedEntrypoint = { entrypoint: ep, variableName };
|
|
6430
6530
|
}
|
|
6431
6531
|
}
|
|
6432
6532
|
let djangoStatic = null;
|
|
@@ -6441,7 +6541,7 @@ var frameworkHooks = {
|
|
|
6441
6541
|
djangoSettings
|
|
6442
6542
|
);
|
|
6443
6543
|
}
|
|
6444
|
-
return { entrypoint
|
|
6544
|
+
return { entrypoint: resolvedEntrypoint, djangoStatic };
|
|
6445
6545
|
}
|
|
6446
6546
|
};
|
|
6447
6547
|
async function downloadFilesInWorkPath({
|
|
@@ -6454,7 +6554,8 @@ async function downloadFilesInWorkPath({
|
|
|
6454
6554
|
let downloadedFiles = await (0, import_build_utils14.download)(files, workPath, meta);
|
|
6455
6555
|
if (meta.isDev) {
|
|
6456
6556
|
const { devCacheDir = (0, import_path13.join)(workPath, ".now", "cache") } = meta;
|
|
6457
|
-
const
|
|
6557
|
+
const cacheKey = (0, import_path13.basename)(entrypoint).replace(/\./g, "_");
|
|
6558
|
+
const destCache = (0, import_path13.join)(devCacheDir, cacheKey);
|
|
6458
6559
|
await (0, import_build_utils14.download)(downloadedFiles, destCache);
|
|
6459
6560
|
downloadedFiles = await (0, import_build_utils14.glob)("**", destCache);
|
|
6460
6561
|
workPath = destCache;
|
|
@@ -6505,9 +6606,9 @@ var build = async ({
|
|
|
6505
6606
|
) ?? void 0;
|
|
6506
6607
|
if (detected?.entrypoint) {
|
|
6507
6608
|
(0, import_build_utils14.debug)(
|
|
6508
|
-
`Resolved Python entrypoint to "${detected.entrypoint}" (configured "${entrypoint}" not found).`
|
|
6609
|
+
`Resolved Python entrypoint to "${detected.entrypoint.entrypoint}" (configured "${entrypoint}" not found).`
|
|
6509
6610
|
);
|
|
6510
|
-
entrypoint = detected.entrypoint;
|
|
6611
|
+
entrypoint = detected.entrypoint.entrypoint;
|
|
6511
6612
|
} else {
|
|
6512
6613
|
const searchedList = PYTHON_CANDIDATE_ENTRYPOINTS.join(", ");
|
|
6513
6614
|
entrypointNotFound = new import_build_utils14.NowBuildError({
|
|
@@ -6518,6 +6619,27 @@ var build = async ({
|
|
|
6518
6619
|
});
|
|
6519
6620
|
}
|
|
6520
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
|
+
}
|
|
6521
6643
|
if (entrypointNotFound && detected?.baseDir === void 0) {
|
|
6522
6644
|
throw entrypointNotFound;
|
|
6523
6645
|
}
|
|
@@ -6592,8 +6714,11 @@ var build = async ({
|
|
|
6592
6714
|
let uv;
|
|
6593
6715
|
try {
|
|
6594
6716
|
const uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
|
|
6595
|
-
console.log(`Using uv at "${uvPath}"`);
|
|
6596
6717
|
uv = new UvRunner(uvPath);
|
|
6718
|
+
const uvVersionOutput = (0, import_child_process3.execSync)(`${uvPath} --version`, {
|
|
6719
|
+
encoding: "utf8"
|
|
6720
|
+
}).trim();
|
|
6721
|
+
console.log(`Using ${uvVersionOutput}`);
|
|
6597
6722
|
} catch (err) {
|
|
6598
6723
|
console.log("Failed to install or locate uv");
|
|
6599
6724
|
throw new Error(
|
|
@@ -6679,8 +6804,9 @@ var build = async ({
|
|
|
6679
6804
|
entrypoint,
|
|
6680
6805
|
detected
|
|
6681
6806
|
});
|
|
6682
|
-
|
|
6683
|
-
|
|
6807
|
+
const resolved = hookResult?.entrypoint ?? detected?.entrypoint;
|
|
6808
|
+
if (entrypointNotFound && resolved) {
|
|
6809
|
+
entrypoint = resolved.entrypoint;
|
|
6684
6810
|
entrypointNotFound = void 0;
|
|
6685
6811
|
}
|
|
6686
6812
|
if (entrypointNotFound) {
|
|
@@ -6713,7 +6839,7 @@ var build = async ({
|
|
|
6713
6839
|
if (handlerFunction) {
|
|
6714
6840
|
const entrypointPath = (0, import_path13.join)(workPath, entrypoint);
|
|
6715
6841
|
const source = await import_fs11.default.promises.readFile(entrypointPath, "utf-8");
|
|
6716
|
-
const found = await (0,
|
|
6842
|
+
const found = await (0, import_python_analysis9.containsTopLevelCallable)(source, handlerFunction);
|
|
6717
6843
|
if (!found) {
|
|
6718
6844
|
throw new import_build_utils14.NowBuildError({
|
|
6719
6845
|
code: "PYTHON_HANDLER_NOT_FOUND",
|
|
@@ -6727,7 +6853,7 @@ var build = async ({
|
|
|
6727
6853
|
(0, import_build_utils14.debug)("Entrypoint with suffix is", entrypointWithSuffix);
|
|
6728
6854
|
const handlerFuncEnvLine = handlerFunction ? `
|
|
6729
6855
|
"__VC_HANDLER_FUNC_NAME": "${handlerFunction}",` : "";
|
|
6730
|
-
const variableName =
|
|
6856
|
+
const variableName = resolved?.variableName ?? "";
|
|
6731
6857
|
const runtimeTrampoline = `
|
|
6732
6858
|
import importlib
|
|
6733
6859
|
import os
|
|
@@ -6872,7 +6998,24 @@ from vercel_runtime.vc_init import vc_handler
|
|
|
6872
6998
|
);
|
|
6873
6999
|
}
|
|
6874
7000
|
}
|
|
6875
|
-
|
|
7001
|
+
if (djangoStatic?.cdnOutputDir) {
|
|
7002
|
+
const lambdaPath = entrypoint.replace(/\.py$/, "");
|
|
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
|
+
};
|
|
7017
|
+
}
|
|
7018
|
+
return { resultVersion: 3, result: { output } };
|
|
6876
7019
|
};
|
|
6877
7020
|
var shouldServe = (opts) => {
|
|
6878
7021
|
const framework = opts.config.framework;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/python",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.28.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"directory": "packages/python"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@vercel/python-analysis": "0.
|
|
18
|
+
"@vercel/python-analysis": "0.11.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@renovatebot/pep440": "4.2.1",
|
|
@@ -36,14 +36,14 @@
|
|
|
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.10.0",
|
|
40
|
+
"@vercel/python-runtime": "0.11.0",
|
|
41
|
+
"@vercel/error-utils": "2.0.3"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "node ../../utils/build-builder.mjs",
|
|
45
45
|
"type-check": "tsc --noEmit",
|
|
46
|
-
"test": "cross-env VERCEL_FORCE_PYTHON_STREAMING=1 jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail",
|
|
46
|
+
"test": "cross-env VERCEL_FORCE_PYTHON_STREAMING=1 NODE_OPTIONS=--experimental-vm-modules jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail",
|
|
47
47
|
"test-unit": "vitest run --config ../../vitest.config.mts test/unit.test.ts",
|
|
48
48
|
"test-e2e": "pnpm test test/integration-*",
|
|
49
49
|
"vitest-run": "vitest -c ../../vitest.config.mts",
|