@vercel/python 6.50.0 → 6.51.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +61 -34
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -5898,6 +5898,7 @@ var LAMBDA_EPHEMERAL_STORAGE_BYTES = 500 * 1024 * 1024;
5898
5898
  var EPHEMERAL_INSTALL_BUDGET_BYTES = LAMBDA_EPHEMERAL_STORAGE_BYTES - 50 * 1024 * 1024;
5899
5899
  var RUNTIME_DEPS_DIR = "/tmp/_vc_deps";
5900
5900
  var MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE = 5 * 1024 * 1024 * 1024;
5901
+ var LARGE_FUNCTION_FILL_CEILING_BYTES = MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE - BYTECODE_FILL_MARGIN_BYTES;
5901
5902
  var BUNDLING_DOCS_LINK = "https://vercel.com/docs/functions/runtimes/python#controlling-what-gets-bundled";
5902
5903
  var PythonDependencyExternalizer = class {
5903
5904
  constructor(options) {
@@ -6753,12 +6754,6 @@ async function calculateBundleSize(files, filter) {
6753
6754
  }
6754
6755
  return totalSize;
6755
6756
  }
6756
- var PYC_TO_PY_RATIO = 1.2;
6757
- var BYTECODE_COVERAGE_FLOOR = 0.5;
6758
- async function estimateBytecodeSize(files) {
6759
- const pyBytes = await calculateBundleSize(files, (p) => p.endsWith(".py"));
6760
- return PYC_TO_PY_RATIO * pyBytes;
6761
- }
6762
6757
  function lambdaKnapsack(packages, capacity) {
6763
6758
  if (capacity <= 0) {
6764
6759
  return [];
@@ -8072,24 +8067,34 @@ var startDevServer = async (opts) => {
8072
8067
  installGlobalCleanupHandlers();
8073
8068
  const env = { ...process.env, ...meta.env || {} };
8074
8069
  const entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
8070
+ const isPyprojectEntrypoint = entrypoint === "pyproject.toml";
8075
8071
  let resolved;
8076
8072
  const handlerFunction = typeof config?.handlerFunction === "string" ? config.handlerFunction : void 0;
8077
- const detected = await detectPythonEntrypoint(
8078
- framework,
8079
- workPath,
8080
- entrypoint ? {
8081
- filePath: entrypoint,
8082
- // Schedule-triggered services create their own "app" wrapper dynamically.
8083
- // Other services use handlerFunction as the entrypoint variable name.
8084
- varName: service && (0, import_build_utils13.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
8085
- } : void 0,
8086
- service,
8087
- opts.repoRootPath
8088
- );
8073
+ let detected;
8074
+ if (isPyprojectEntrypoint) {
8075
+ const declaredEntrypoint = await getVercelToolsEntrypoint(
8076
+ workPath,
8077
+ opts.repoRootPath
8078
+ );
8079
+ detected = declaredEntrypoint ? { entrypoint: declaredEntrypoint } : null;
8080
+ } else {
8081
+ detected = await detectPythonEntrypoint(
8082
+ framework,
8083
+ workPath,
8084
+ entrypoint ? {
8085
+ filePath: entrypoint,
8086
+ // Schedule-triggered services create their own "app" wrapper dynamically.
8087
+ // Other services use handlerFunction as the entrypoint variable name.
8088
+ varName: service && (0, import_build_utils13.isScheduleTriggeredService)(service) ? void 0 : handlerFunction
8089
+ } : void 0,
8090
+ service,
8091
+ opts.repoRootPath
8092
+ );
8093
+ }
8089
8094
  let hookResult;
8090
8095
  if (detected?.entrypoint) {
8091
8096
  resolved = detected.entrypoint;
8092
- } else {
8097
+ } else if (!isPyprojectEntrypoint) {
8093
8098
  hookResult = await runFrameworkHook(framework, {
8094
8099
  pythonEnv: env,
8095
8100
  workPath,
@@ -8103,8 +8108,8 @@ var startDevServer = async (opts) => {
8103
8108
  throw detected.error;
8104
8109
  }
8105
8110
  throw new import_build_utils13.NowBuildError({
8106
- code: "PYTHON_ENTRYPOINT_NOT_FOUND",
8107
- message: "No Python entrypoint could be detected. Please specify an entrypoint file."
8111
+ code: isPyprojectEntrypoint ? "PYTHON_PYPROJECT_NOTHING_TO_BUILD" : "PYTHON_ENTRYPOINT_NOT_FOUND",
8112
+ message: isPyprojectEntrypoint ? 'Entrypoint "pyproject.toml" does not declare a web app. Set "tool.vercel.entrypoint" in pyproject.toml.' : "No Python entrypoint could be detected. Please specify an entrypoint file."
8108
8113
  });
8109
8114
  }
8110
8115
  const { entrypoint: entry, variableName } = resolved;
@@ -9174,10 +9179,13 @@ function getDevSubscriberTopics(subscriber) {
9174
9179
  }
9175
9180
  async function getDevSidecars({
9176
9181
  workPath,
9177
- build: build2
9182
+ build: build2,
9183
+ service
9178
9184
  }) {
9179
9185
  const framework = build2.config?.framework;
9180
- if (build2.config?.middleware === true || typeof framework !== "string" || !(0, import_build_utils20.isPythonFramework)(framework)) {
9186
+ const isPyprojectEntrypoint = (0, import_path17.basename)(build2.src ?? "") === "pyproject.toml";
9187
+ const isPyprojectService = service !== void 0 && (0, import_path17.basename)(service.entrypoint ?? "") === "pyproject.toml";
9188
+ if (build2.config?.middleware === true || service !== void 0 && !isPyprojectService || service === void 0 && !isPyprojectEntrypoint && (typeof framework !== "string" || !(0, import_build_utils20.isPythonFramework)(framework))) {
9181
9189
  return [];
9182
9190
  }
9183
9191
  const subscribers = await getPyprojectSubscribers(workPath);
@@ -9189,7 +9197,7 @@ async function getDevSidecars({
9189
9197
  name: subscriber.name,
9190
9198
  consumer: getSubscriberConsumerName(subscriber.name),
9191
9199
  workspace: ".",
9192
- framework,
9200
+ framework: typeof framework === "string" ? framework : void 0,
9193
9201
  runtime: "python",
9194
9202
  builder: {
9195
9203
  use: build2.use,
@@ -9207,7 +9215,7 @@ async function getDevSidecars({
9207
9215
  name: workflow.name,
9208
9216
  consumer: getWorkflowConsumerName(workflow.name),
9209
9217
  workspace: ".",
9210
- framework,
9218
+ framework: typeof framework === "string" ? framework : void 0,
9211
9219
  runtime: "python",
9212
9220
  builder: {
9213
9221
  use: build2.use,
@@ -10124,16 +10132,19 @@ var build = async ({
10124
10132
  const announceLargeFunction = () => console.log(
10125
10133
  `Function "${entrypoint ?? rawEntrypoint}" exceeds the standard size limit; enabling large functions (beta).`
10126
10134
  );
10135
+ let packingMode;
10127
10136
  if (depAnalysis.runtimeInstallEnabled) {
10137
+ packingMode = "runtime-install";
10128
10138
  const bytecodeFirst = compileAllEnabled && pythonVersion.major != null && pythonVersion.minor != null;
10129
10139
  const bundleResult = await depExternalizer.generateBundle(files, {
10130
10140
  bytecodeFirst
10131
10141
  });
10132
10142
  if (bundleResult.fellBackToFullBundle) {
10143
+ packingMode = "hive";
10133
10144
  announceLargeFunction();
10134
10145
  if (compileAllEnabled) {
10135
10146
  await runCompileAllAndFillBytecode(
10136
- MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE
10147
+ LARGE_FUNCTION_FILL_CEILING_BYTES
10137
10148
  );
10138
10149
  }
10139
10150
  } else if (bundleResult.packingMode === "bytecode-first") {
@@ -10141,33 +10152,49 @@ var build = async ({
10141
10152
  } else if (compileAllEnabled) {
10142
10153
  const currentSize = await calculateBundleSize(files);
10143
10154
  const capacity = BYTECODE_FILL_CEILING_BYTES - currentSize;
10144
- const estimate = await estimateBytecodeSize(files);
10145
- if (capacity >= BYTECODE_COVERAGE_FLOOR * estimate) {
10155
+ if (capacity > 0) {
10146
10156
  await runCompileAllAndFillBytecode(BYTECODE_FILL_CEILING_BYTES, [
10147
10157
  bundleResult.alwaysBundledPackages ?? [],
10148
10158
  bundleResult.bundledPublicPackages ?? []
10149
10159
  ]);
10160
+ } else {
10161
+ (0, import_build_utils20.debug)(
10162
+ `skipping bytecode precompilation: no zip capacity remaining (bundle is ${(currentSize / (1024 * 1024)).toFixed(2)} MB)`
10163
+ );
10150
10164
  }
10151
10165
  }
10152
10166
  } else {
10153
10167
  addFiles(files, depAnalysis.allVendorFiles);
10154
10168
  if (depAnalysis.totalBundleSize > LAMBDA_SIZE_THRESHOLD_BYTES) {
10169
+ packingMode = "hive";
10155
10170
  if (isLargeFunctionsEnabled()) {
10156
10171
  announceLargeFunction();
10157
10172
  }
10158
10173
  if (compileAllEnabled) {
10159
10174
  await runCompileAllAndFillBytecode(
10160
- MAX_LARGE_FUNCTION_UNCOMPRESSED_SIZE
10175
+ LARGE_FUNCTION_FILL_CEILING_BYTES
10161
10176
  );
10162
10177
  }
10163
- } else if (compileAllEnabled) {
10164
- const capacity = BYTECODE_FILL_CEILING_BYTES - depAnalysis.totalBundleSize;
10165
- const estimate = await estimateBytecodeSize(files);
10166
- if (capacity >= BYTECODE_COVERAGE_FLOOR * estimate) {
10167
- await runCompileAllAndFillBytecode(BYTECODE_FILL_CEILING_BYTES);
10178
+ } else {
10179
+ packingMode = "standard";
10180
+ if (compileAllEnabled) {
10181
+ const capacity = BYTECODE_FILL_CEILING_BYTES - depAnalysis.totalBundleSize;
10182
+ if (capacity > 0) {
10183
+ await runCompileAllAndFillBytecode(BYTECODE_FILL_CEILING_BYTES);
10184
+ } else {
10185
+ (0, import_build_utils20.debug)(
10186
+ `skipping bytecode precompilation: no zip capacity remaining (bundle is ${(depAnalysis.totalBundleSize / (1024 * 1024)).toFixed(2)} MB)`
10187
+ );
10188
+ }
10168
10189
  }
10169
10190
  }
10170
10191
  }
10192
+ bundleSpan.setAttributes({
10193
+ "python.bundle.totalSizeBytes": String(
10194
+ await calculateBundleSize(files)
10195
+ ),
10196
+ "python.bundle.packingMode": packingMode
10197
+ });
10171
10198
  });
10172
10199
  let output;
10173
10200
  if (entrypoint && runtimeTrampoline) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "6.50.0",
3
+ "version": "6.51.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/python-runtime": "0.16.0",
40
- "@vercel/build-utils": "13.33.0",
41
- "@vercel/error-utils": "2.2.0"
39
+ "@vercel/error-utils": "2.2.0",
40
+ "@vercel/build-utils": "13.34.0",
41
+ "@vercel/python-runtime": "0.16.0"
42
42
  },
43
43
  "scripts": {
44
44
  "build": "node ../../utils/build-builder.mjs",