@vercel/python 6.16.0 → 6.17.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 +142 -48
- package/package.json +5 -5
- package/vc_init_dev.py +17 -5
package/dist/index.js
CHANGED
|
@@ -2871,8 +2871,8 @@ var import_fs6 = __toESM(require("fs"));
|
|
|
2871
2871
|
var import_util2 = require("util");
|
|
2872
2872
|
var import_path8 = require("path");
|
|
2873
2873
|
|
|
2874
|
-
// src/
|
|
2875
|
-
var VERCEL_RUNTIME_VERSION = "0.5.
|
|
2874
|
+
// src/package-versions.ts
|
|
2875
|
+
var VERCEL_RUNTIME_VERSION = "0.5.2";
|
|
2876
2876
|
|
|
2877
2877
|
// src/index.ts
|
|
2878
2878
|
var import_build_utils9 = require("@vercel/build-utils");
|
|
@@ -3880,6 +3880,19 @@ var PythonDependencyExternalizer = class {
|
|
|
3880
3880
|
this.projectName = options.projectName;
|
|
3881
3881
|
this.noBuildCheckFailed = options.noBuildCheckFailed;
|
|
3882
3882
|
this.pythonPath = options.pythonPath;
|
|
3883
|
+
this.hasCustomCommand = options.hasCustomCommand;
|
|
3884
|
+
}
|
|
3885
|
+
shouldEnableRuntimeInstall() {
|
|
3886
|
+
if (this.hasCustomCommand) {
|
|
3887
|
+
return false;
|
|
3888
|
+
}
|
|
3889
|
+
const pythonOnHiveEnabled = process.env.VERCEL_PYTHON_ON_HIVE === "1" || process.env.VERCEL_PYTHON_ON_HIVE === "true";
|
|
3890
|
+
if (pythonOnHiveEnabled) {
|
|
3891
|
+
return false;
|
|
3892
|
+
} else if (this.totalBundleSize > LAMBDA_SIZE_THRESHOLD_BYTES && this.uvLockPath !== null) {
|
|
3893
|
+
return true;
|
|
3894
|
+
}
|
|
3895
|
+
return false;
|
|
3883
3896
|
}
|
|
3884
3897
|
/**
|
|
3885
3898
|
* Analyze the bundle: mirror all vendor files, calculate total size,
|
|
@@ -3899,11 +3912,24 @@ var PythonDependencyExternalizer = class {
|
|
|
3899
3912
|
this.analyzed = true;
|
|
3900
3913
|
const totalBundleSizeMB = (this.totalBundleSize / (1024 * 1024)).toFixed(2);
|
|
3901
3914
|
(0, import_build_utils5.debug)(`Total bundle size: ${totalBundleSizeMB} MB`);
|
|
3902
|
-
const
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3915
|
+
const runtimeInstallEnabled = this.shouldEnableRuntimeInstall();
|
|
3916
|
+
const pythonOnHiveEnabled = process.env.VERCEL_PYTHON_ON_HIVE === "1" || process.env.VERCEL_PYTHON_ON_HIVE === "true";
|
|
3917
|
+
if (this.totalBundleSize > LAMBDA_SIZE_THRESHOLD_BYTES && this.hasCustomCommand && !pythonOnHiveEnabled) {
|
|
3918
|
+
const limitMB = (LAMBDA_SIZE_THRESHOLD_BYTES / (1024 * 1024)).toFixed(0);
|
|
3919
|
+
throw new import_build_utils5.NowBuildError({
|
|
3920
|
+
code: "LAMBDA_SIZE_EXCEEDED",
|
|
3921
|
+
message: `Total bundle size (${totalBundleSizeMB} MB) exceeds the Lambda size limit (${limitMB} MB).
|
|
3922
|
+
|
|
3923
|
+
Runtime dependency installation is not available for projects that use a custom build or install command, because custom commands may install dependencies that are not tracked in uv.lock.
|
|
3924
|
+
|
|
3925
|
+
To resolve this, either:
|
|
3926
|
+
1. Remove the custom build/install command and let Vercel manage dependencies automatically
|
|
3927
|
+
2. Reduce your dependency footprint to fit within the ${limitMB} MB limit`,
|
|
3928
|
+
link: "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled",
|
|
3929
|
+
action: "Learn More"
|
|
3930
|
+
});
|
|
3931
|
+
}
|
|
3932
|
+
return { runtimeInstallEnabled, allVendorFiles: this.allVendorFiles };
|
|
3907
3933
|
}
|
|
3908
3934
|
/**
|
|
3909
3935
|
* Generate the optimally-packed Lambda bundle.
|
|
@@ -3931,7 +3957,9 @@ var PythonDependencyExternalizer = class {
|
|
|
3931
3957
|
const ephemeralLimitMB = (LAMBDA_EPHEMERAL_STORAGE_BYTES / (1024 * 1024)).toFixed(0);
|
|
3932
3958
|
throw new import_build_utils5.NowBuildError({
|
|
3933
3959
|
code: "LAMBDA_SIZE_EXCEEDED",
|
|
3934
|
-
message: `Total dependency size (${totalBundleSizeMB} MB) exceeds Lambda ephemeral storage limit (${ephemeralLimitMB} MB). Even with runtime dependency installation, all packages must fit within the ${ephemeralLimitMB} MB ephemeral storage available to Lambda functions. Consider removing unused dependencies or splitting your application into smaller functions
|
|
3960
|
+
message: `Total dependency size (${totalBundleSizeMB} MB) exceeds Lambda ephemeral storage limit (${ephemeralLimitMB} MB). Even with runtime dependency installation, all packages must fit within the ${ephemeralLimitMB} MB ephemeral storage available to Lambda functions. Consider removing unused dependencies or splitting your application into smaller functions.`,
|
|
3961
|
+
link: "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled",
|
|
3962
|
+
action: "Learn More"
|
|
3935
3963
|
});
|
|
3936
3964
|
}
|
|
3937
3965
|
if (this.noBuildCheckFailed) {
|
|
@@ -4097,23 +4125,13 @@ ${error.fileContent}`
|
|
|
4097
4125
|
const limitMB = (LAMBDA_SIZE_THRESHOLD_BYTES / (1024 * 1024)).toFixed(0);
|
|
4098
4126
|
throw new import_build_utils5.NowBuildError({
|
|
4099
4127
|
code: "LAMBDA_SIZE_EXCEEDED",
|
|
4100
|
-
message: `Bundle size (${finalSizeMB} MB) exceeds Lambda limit (${limitMB} MB) even after deferring public packages to runtime installation. This usually means your private packages or source code are too large. Consider reducing the size of private dependencies or splitting your application
|
|
4128
|
+
message: `Bundle size (${finalSizeMB} MB) exceeds Lambda limit (${limitMB} MB) even after deferring public packages to runtime installation. This usually means your private packages or source code are too large. Consider reducing the size of private dependencies or splitting your application.`,
|
|
4129
|
+
link: "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled",
|
|
4130
|
+
action: "Learn More"
|
|
4101
4131
|
});
|
|
4102
4132
|
}
|
|
4103
4133
|
}
|
|
4104
4134
|
};
|
|
4105
|
-
function shouldEnableRuntimeInstall({
|
|
4106
|
-
totalBundleSize,
|
|
4107
|
-
uvLockPath
|
|
4108
|
-
}) {
|
|
4109
|
-
const pythonOnHiveEnabled = process.env.VERCEL_PYTHON_ON_HIVE === "1" || process.env.VERCEL_PYTHON_ON_HIVE === "true";
|
|
4110
|
-
if (pythonOnHiveEnabled) {
|
|
4111
|
-
return false;
|
|
4112
|
-
} else if (totalBundleSize > LAMBDA_SIZE_THRESHOLD_BYTES && uvLockPath !== null) {
|
|
4113
|
-
return true;
|
|
4114
|
-
}
|
|
4115
|
-
return false;
|
|
4116
|
-
}
|
|
4117
4135
|
async function mirrorPackagesIntoVendor({
|
|
4118
4136
|
venvPath,
|
|
4119
4137
|
vendorDirName,
|
|
@@ -4246,11 +4264,16 @@ var PYTHON_ENTRYPOINT_FILENAMES = [
|
|
|
4246
4264
|
"asgi"
|
|
4247
4265
|
];
|
|
4248
4266
|
var PYTHON_ENTRYPOINT_DIRS = ["", "src", "app", "api"];
|
|
4249
|
-
var PYTHON_CANDIDATE_ENTRYPOINTS =
|
|
4250
|
-
|
|
4251
|
-
(dir) => import_path6.posix.join(dir, `${filename}.py`)
|
|
4252
|
-
)
|
|
4267
|
+
var PYTHON_CANDIDATE_ENTRYPOINTS = getCandidateEntrypointsInDirs(
|
|
4268
|
+
PYTHON_ENTRYPOINT_DIRS
|
|
4253
4269
|
);
|
|
4270
|
+
function getCandidateEntrypointsInDirs(dirs) {
|
|
4271
|
+
return dirs.flatMap(
|
|
4272
|
+
(dir) => PYTHON_ENTRYPOINT_FILENAMES.map(
|
|
4273
|
+
(filename) => import_path6.posix.join(dir, `${filename}.py`)
|
|
4274
|
+
)
|
|
4275
|
+
);
|
|
4276
|
+
}
|
|
4254
4277
|
async function getPyprojectEntrypoint(workPath) {
|
|
4255
4278
|
const pyprojectData = await (0, import_build_utils7.readConfigFile)((0, import_path6.join)(workPath, "pyproject.toml"));
|
|
4256
4279
|
if (!pyprojectData)
|
|
@@ -4277,6 +4300,18 @@ async function getPyprojectEntrypoint(workPath) {
|
|
|
4277
4300
|
return null;
|
|
4278
4301
|
}
|
|
4279
4302
|
}
|
|
4303
|
+
async function findValidEntrypoint(fsFiles, candidates) {
|
|
4304
|
+
for (const candidate of candidates) {
|
|
4305
|
+
if (fsFiles[candidate]) {
|
|
4306
|
+
const isValid = await (0, import_build_utils6.isPythonEntrypoint)(fsFiles[candidate]);
|
|
4307
|
+
if (isValid) {
|
|
4308
|
+
(0, import_build_utils6.debug)(`Detected Python entrypoint: ${candidate}`);
|
|
4309
|
+
return candidate;
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
return null;
|
|
4314
|
+
}
|
|
4280
4315
|
async function detectGenericPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
4281
4316
|
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
4282
4317
|
try {
|
|
@@ -4291,24 +4326,54 @@ async function detectGenericPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
|
4291
4326
|
const candidates = PYTHON_CANDIDATE_ENTRYPOINTS.filter(
|
|
4292
4327
|
(c) => !!fsFiles[c]
|
|
4293
4328
|
);
|
|
4294
|
-
|
|
4295
|
-
|
|
4329
|
+
return findValidEntrypoint(fsFiles, candidates);
|
|
4330
|
+
} catch {
|
|
4331
|
+
(0, import_build_utils6.debug)("Failed to discover Python entrypoint");
|
|
4332
|
+
return null;
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
async function detectDjangoPythonEntrypoint(workPath, configuredEntrypoint) {
|
|
4336
|
+
const entry = configuredEntrypoint.endsWith(".py") ? configuredEntrypoint : `${configuredEntrypoint}.py`;
|
|
4337
|
+
try {
|
|
4338
|
+
const fsFiles = await (0, import_build_utils6.glob)("**", workPath);
|
|
4339
|
+
if (fsFiles[entry]) {
|
|
4340
|
+
const isValid = await (0, import_build_utils6.isPythonEntrypoint)(fsFiles[entry]);
|
|
4296
4341
|
if (isValid) {
|
|
4297
|
-
(0, import_build_utils6.debug)(`
|
|
4298
|
-
return
|
|
4342
|
+
(0, import_build_utils6.debug)(`Using configured Python entrypoint: ${entry}`);
|
|
4343
|
+
return entry;
|
|
4299
4344
|
}
|
|
4300
4345
|
}
|
|
4301
|
-
|
|
4346
|
+
const rootGlobs = await (0, import_build_utils6.glob)("*", {
|
|
4347
|
+
cwd: workPath,
|
|
4348
|
+
includeDirectories: true
|
|
4349
|
+
});
|
|
4350
|
+
const rootDirs = [
|
|
4351
|
+
"",
|
|
4352
|
+
...Object.keys(rootGlobs).filter(
|
|
4353
|
+
(name) => !name.startsWith(".") && rootGlobs[name].mode != null && (0, import_build_utils6.isDirectory)(rootGlobs[name].mode)
|
|
4354
|
+
)
|
|
4355
|
+
];
|
|
4356
|
+
for (const rootDir of rootDirs) {
|
|
4357
|
+
const currPath = (0, import_path6.join)(workPath, rootDir);
|
|
4358
|
+
const wsgiEntry = await (0, import_build_utils6.getDjangoEntrypoint)(currPath);
|
|
4359
|
+
if (wsgiEntry) {
|
|
4360
|
+
const fullWsgiEntry = import_path6.posix.join(rootDir, wsgiEntry);
|
|
4361
|
+
if (fsFiles[fullWsgiEntry]) {
|
|
4362
|
+
(0, import_build_utils6.debug)(`Using Django WSGI entrypoint: ${fullWsgiEntry}`);
|
|
4363
|
+
return fullWsgiEntry;
|
|
4364
|
+
}
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
const baseCandidates = getCandidateEntrypointsInDirs(rootDirs);
|
|
4368
|
+
const candidates = baseCandidates.filter((c) => !!fsFiles[c]);
|
|
4369
|
+
return findValidEntrypoint(fsFiles, candidates);
|
|
4302
4370
|
} catch {
|
|
4303
|
-
(0, import_build_utils6.debug)("Failed to discover Python entrypoint");
|
|
4371
|
+
(0, import_build_utils6.debug)("Failed to discover Django Python entrypoint");
|
|
4304
4372
|
return null;
|
|
4305
4373
|
}
|
|
4306
4374
|
}
|
|
4307
|
-
async function detectPythonEntrypoint(
|
|
4308
|
-
const entrypoint = await detectGenericPythonEntrypoint(
|
|
4309
|
-
workPath,
|
|
4310
|
-
configuredEntrypoint
|
|
4311
|
-
);
|
|
4375
|
+
async function detectPythonEntrypoint(framework, workPath, configuredEntrypoint) {
|
|
4376
|
+
const entrypoint = framework === "django" ? await detectDjangoPythonEntrypoint(workPath, configuredEntrypoint) : await detectGenericPythonEntrypoint(workPath, configuredEntrypoint);
|
|
4312
4377
|
if (entrypoint)
|
|
4313
4378
|
return entrypoint;
|
|
4314
4379
|
return await getPyprojectEntrypoint(workPath);
|
|
@@ -4561,17 +4626,25 @@ function installGlobalCleanupHandlers() {
|
|
|
4561
4626
|
killAll();
|
|
4562
4627
|
});
|
|
4563
4628
|
}
|
|
4564
|
-
function createDevShim(workPath, modulePath) {
|
|
4629
|
+
function createDevShim(workPath, entry, modulePath) {
|
|
4565
4630
|
try {
|
|
4566
4631
|
const vercelPythonDir = (0, import_path7.join)(workPath, ".vercel", "python");
|
|
4567
4632
|
(0, import_fs5.mkdirSync)(vercelPythonDir, { recursive: true });
|
|
4633
|
+
let qualifiedModule = modulePath;
|
|
4634
|
+
let extraPythonPath;
|
|
4635
|
+
if ((0, import_fs5.existsSync)((0, import_path7.join)(workPath, "__init__.py"))) {
|
|
4636
|
+
const pkgName = (0, import_path7.basename)(workPath);
|
|
4637
|
+
qualifiedModule = `${pkgName}.${modulePath}`;
|
|
4638
|
+
extraPythonPath = (0, import_path7.dirname)(workPath);
|
|
4639
|
+
}
|
|
4640
|
+
const entryAbs = (0, import_path7.join)(workPath, entry);
|
|
4568
4641
|
const shimPath = (0, import_path7.join)(vercelPythonDir, `${DEV_SHIM_MODULE}.py`);
|
|
4569
4642
|
const templatePath = (0, import_path7.join)(__dirname, "..", `${DEV_SHIM_MODULE}.py`);
|
|
4570
4643
|
const template = (0, import_fs5.readFileSync)(templatePath, "utf8");
|
|
4571
|
-
const shimSource = template.replace(/
|
|
4644
|
+
const shimSource = template.replace(/__VC_DEV_MODULE_NAME__/g, qualifiedModule).replace(/__VC_DEV_ENTRY_ABS__/g, entryAbs);
|
|
4572
4645
|
(0, import_fs5.writeFileSync)(shimPath, shimSource, "utf8");
|
|
4573
4646
|
(0, import_build_utils8.debug)(`Prepared Python dev shim at ${shimPath}`);
|
|
4574
|
-
return DEV_SHIM_MODULE;
|
|
4647
|
+
return { module: DEV_SHIM_MODULE, extraPythonPath };
|
|
4575
4648
|
} catch (err) {
|
|
4576
4649
|
(0, import_build_utils8.debug)(`Failed to prepare dev shim: ${err?.message || err}`);
|
|
4577
4650
|
return null;
|
|
@@ -4735,22 +4808,33 @@ If you are using a virtual environment, activate it before running "vercel dev",
|
|
|
4735
4808
|
}
|
|
4736
4809
|
const port = typeof meta.port === "number" ? meta.port : await (0, import_get_port.default)();
|
|
4737
4810
|
env.PORT = `${port}`;
|
|
4738
|
-
const
|
|
4739
|
-
if (
|
|
4811
|
+
const devShim = createDevShim(workPath, entry, modulePath);
|
|
4812
|
+
if (devShim) {
|
|
4740
4813
|
const vercelPythonDir = (0, import_path7.join)(workPath, ".vercel", "python");
|
|
4814
|
+
const pathParts = [vercelPythonDir];
|
|
4815
|
+
if (devShim.extraPythonPath) {
|
|
4816
|
+
pathParts.push(devShim.extraPythonPath);
|
|
4817
|
+
}
|
|
4741
4818
|
const existingPythonPath = env.PYTHONPATH || "";
|
|
4742
|
-
|
|
4819
|
+
if (existingPythonPath) {
|
|
4820
|
+
pathParts.push(existingPythonPath);
|
|
4821
|
+
}
|
|
4822
|
+
env.PYTHONPATH = pathParts.join(import_path7.delimiter);
|
|
4743
4823
|
}
|
|
4744
|
-
const moduleToRun =
|
|
4824
|
+
const moduleToRun = devShim?.module || modulePath;
|
|
4745
4825
|
const pythonArgs = ["-u", "-m", moduleToRun];
|
|
4746
4826
|
const argv = [...spawnArgsPrefix, ...pythonArgs];
|
|
4747
4827
|
(0, import_build_utils8.debug)(
|
|
4748
4828
|
`Starting Python dev server (${framework}): ${spawnCommand} ${argv.join(" ")} [PORT=${port}]`
|
|
4749
4829
|
);
|
|
4830
|
+
if (process.stdout.columns) {
|
|
4831
|
+
env.COLUMNS = `${process.stdout.columns}`;
|
|
4832
|
+
}
|
|
4750
4833
|
const child = (0, import_child_process2.spawn)(spawnCommand, argv, {
|
|
4751
4834
|
cwd: workPath,
|
|
4752
4835
|
env,
|
|
4753
|
-
stdio: ["
|
|
4836
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
4837
|
+
detached: true
|
|
4754
4838
|
});
|
|
4755
4839
|
childProcess = child;
|
|
4756
4840
|
stdoutLogListener = createLogListener(onStdout, process.stdout);
|
|
@@ -4825,6 +4909,7 @@ var build = async ({
|
|
|
4825
4909
|
const framework = config?.framework;
|
|
4826
4910
|
let spawnEnv;
|
|
4827
4911
|
let projectInstallCommand;
|
|
4912
|
+
let hasCustomCommand = false;
|
|
4828
4913
|
(0, import_build_utils9.debug)(`workPath: ${workPath}`);
|
|
4829
4914
|
workPath = await downloadFilesInWorkPath({
|
|
4830
4915
|
workPath,
|
|
@@ -4873,12 +4958,16 @@ var build = async ({
|
|
|
4873
4958
|
env: spawnEnv,
|
|
4874
4959
|
cwd: workPath
|
|
4875
4960
|
});
|
|
4961
|
+
hasCustomCommand = true;
|
|
4876
4962
|
} else {
|
|
4877
|
-
await runPyprojectScript(
|
|
4963
|
+
const ranBuildScript = await runPyprojectScript(
|
|
4878
4964
|
workPath,
|
|
4879
4965
|
["vercel-build", "now-build", "build"],
|
|
4880
4966
|
spawnEnv
|
|
4881
4967
|
);
|
|
4968
|
+
if (ranBuildScript) {
|
|
4969
|
+
hasCustomCommand = true;
|
|
4970
|
+
}
|
|
4882
4971
|
}
|
|
4883
4972
|
}
|
|
4884
4973
|
let fsFiles = await (0, import_build_utils9.glob)("**", workPath);
|
|
@@ -5011,6 +5100,7 @@ ${pipfileLockContent}`
|
|
|
5011
5100
|
cwd: workPath
|
|
5012
5101
|
});
|
|
5013
5102
|
assumeDepsInstalled = true;
|
|
5103
|
+
hasCustomCommand = true;
|
|
5014
5104
|
} else {
|
|
5015
5105
|
assumeDepsInstalled = await runPyprojectScript(
|
|
5016
5106
|
workPath,
|
|
@@ -5019,6 +5109,9 @@ ${pipfileLockContent}`
|
|
|
5019
5109
|
/* useUserVirtualEnv */
|
|
5020
5110
|
false
|
|
5021
5111
|
);
|
|
5112
|
+
if (assumeDepsInstalled) {
|
|
5113
|
+
hasCustomCommand = true;
|
|
5114
|
+
}
|
|
5022
5115
|
}
|
|
5023
5116
|
let uv;
|
|
5024
5117
|
try {
|
|
@@ -5159,10 +5252,11 @@ from vercel_runtime.vc_init import vc_handler
|
|
|
5159
5252
|
uvProjectDir,
|
|
5160
5253
|
projectName,
|
|
5161
5254
|
noBuildCheckFailed,
|
|
5162
|
-
pythonPath: pythonVersion.pythonPath
|
|
5255
|
+
pythonPath: pythonVersion.pythonPath,
|
|
5256
|
+
hasCustomCommand
|
|
5163
5257
|
});
|
|
5164
|
-
const {
|
|
5165
|
-
if (
|
|
5258
|
+
const { runtimeInstallEnabled, allVendorFiles } = await depExternalizer.analyze(files);
|
|
5259
|
+
if (runtimeInstallEnabled) {
|
|
5166
5260
|
await depExternalizer.generateBundle(files);
|
|
5167
5261
|
} else {
|
|
5168
5262
|
for (const [p, f] of Object.entries(allVendorFiles)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/python",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.17.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.8.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@renovatebot/pep440": "4.2.1",
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"which": "3.0.0",
|
|
36
36
|
"get-port": "5.1.1",
|
|
37
37
|
"is-port-reachable": "3.1.0",
|
|
38
|
-
"@vercel/build-utils": "13.
|
|
39
|
-
"@vercel/
|
|
40
|
-
"@vercel/
|
|
38
|
+
"@vercel/build-utils": "13.6.0",
|
|
39
|
+
"@vercel/error-utils": "2.0.3",
|
|
40
|
+
"@vercel/python-runtime": "0.5.2"
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"build": "node ../../utils/build-builder.mjs",
|
package/vc_init_dev.py
CHANGED
|
@@ -5,7 +5,7 @@ import sys
|
|
|
5
5
|
import os
|
|
6
6
|
import inspect
|
|
7
7
|
from os import path as _p
|
|
8
|
-
from importlib import
|
|
8
|
+
from importlib import util as _importlib_util
|
|
9
9
|
import mimetypes
|
|
10
10
|
|
|
11
11
|
|
|
@@ -72,8 +72,20 @@ def _strip_service_route_prefix(path_value):
|
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
# ASGI/WSGI app detection
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
_MODULE_NAME = "__VC_DEV_MODULE_NAME__"
|
|
76
|
+
_ENTRY_ABS = "__VC_DEV_ENTRY_ABS__"
|
|
77
|
+
|
|
78
|
+
# Import user module by file path, matching vc_init.py's approach.
|
|
79
|
+
# https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly
|
|
80
|
+
_spec = _importlib_util.spec_from_file_location(_MODULE_NAME, _ENTRY_ABS)
|
|
81
|
+
if _spec is None or _spec.loader is None:
|
|
82
|
+
raise RuntimeError(
|
|
83
|
+
f"Could not load module spec for '{_MODULE_NAME}' at {_ENTRY_ABS}"
|
|
84
|
+
)
|
|
85
|
+
_mod = _importlib_util.module_from_spec(_spec)
|
|
86
|
+
sys.modules[_MODULE_NAME] = _mod
|
|
87
|
+
_spec.loader.exec_module(_mod)
|
|
88
|
+
|
|
77
89
|
_user_app_name = (
|
|
78
90
|
"app"
|
|
79
91
|
if hasattr(_mod, "app")
|
|
@@ -83,7 +95,7 @@ _user_app_name = (
|
|
|
83
95
|
)
|
|
84
96
|
if _user_app_name is None:
|
|
85
97
|
raise RuntimeError(
|
|
86
|
-
f"Missing 'app' or 'application' in module '{
|
|
98
|
+
f"Missing 'app' or 'application' in module '{_MODULE_NAME}'. "
|
|
87
99
|
f"Define `app = ...` or `application = ...` in your entrypoint."
|
|
88
100
|
)
|
|
89
101
|
|
|
@@ -137,7 +149,7 @@ def _detect_app_type(app_obj):
|
|
|
137
149
|
|
|
138
150
|
print(
|
|
139
151
|
_color(
|
|
140
|
-
f"Could not determine the application interface for '{
|
|
152
|
+
f"Could not determine the application interface for '{_MODULE_NAME}:{_user_app_name}'\n"
|
|
141
153
|
f"Expected either:\n"
|
|
142
154
|
f" - An ASGI app: async callable(scope, receive, send)\n"
|
|
143
155
|
f" - A WSGI app: callable(environ, start_response)",
|