@vercel/python 15.0.0 → 16.0.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 +181 -6
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -12939,6 +12939,7 @@ function getImportClosureOptions({
12939
12939
  }
12940
12940
 
12941
12941
  // src/index.ts
12942
+ var import_build_utils25 = require("@vercel/build-utils");
12942
12943
  var writeFile = import_fs20.default.promises.writeFile;
12943
12944
  var PYTHON_ENTRYPOINT_DOCS_URL2 = "https://vercel.com/docs/functions/runtimes/python#python-entrypoints";
12944
12945
  var version = -1;
@@ -13786,6 +13787,175 @@ async function packFunctionBundle({
13786
13787
  });
13787
13788
  return { pycachePrefix, vendorDir, files };
13788
13789
  }
13790
+ async function buildProxyMiddleware({
13791
+ workPath,
13792
+ repoRootPath,
13793
+ files: originalFiles,
13794
+ entrypoint,
13795
+ config,
13796
+ meta,
13797
+ builderSpan
13798
+ }) {
13799
+ const target = getTargetPlatform(meta.isDev ?? false);
13800
+ (0, import_build_utils24.debug)(`workPath: ${workPath}`);
13801
+ workPath = await downloadFilesInWorkPath({
13802
+ workPath,
13803
+ files: originalFiles,
13804
+ entrypoint,
13805
+ meta
13806
+ });
13807
+ const proxyHandlerFunction = config.handlerFunction;
13808
+ if (typeof proxyHandlerFunction !== "string" || !proxyHandlerFunction) {
13809
+ throw new Error(
13810
+ 'Python proxy build requires "config.handlerFunction" to be set'
13811
+ );
13812
+ }
13813
+ const proxySource = await import_fs20.default.promises.readFile(
13814
+ (0, import_path21.join)(workPath, entrypoint),
13815
+ "utf-8"
13816
+ );
13817
+ if (!await (0, import_python_analysis12.containsTopLevelCallable)(proxySource, proxyHandlerFunction)) {
13818
+ throw new import_build_utils24.NowBuildError({
13819
+ code: "PYTHON_HANDLER_NOT_FOUND",
13820
+ message: `Handler function "${proxyHandlerFunction}" not found in ${entrypoint}. Ensure it is defined at the module's top level.`
13821
+ });
13822
+ }
13823
+ const rootDir = repoRootPath ?? workPath;
13824
+ const venvPath = (0, import_path21.join)(workPath, ".vercel", "python", "vercel.proxy", ".venv");
13825
+ const { pythonPackage, pythonVersion, uv, uvCacheDir, restoredCache } = await setupPythonToolchain({
13826
+ builderSpan,
13827
+ workPath,
13828
+ entrypointDir: (0, import_path21.join)(workPath, (0, import_path21.dirname)(entrypoint)),
13829
+ rootDir,
13830
+ venvPath,
13831
+ meta
13832
+ });
13833
+ const { projectDir, lockPath: uvLockPath } = await builderSpan.child(import_build_utils24.BUILDER_INSTALLER_STEP, {
13834
+ runtime: "python",
13835
+ "python.cache.restored": restoredCache
13836
+ }).trace(
13837
+ () => runUvManagedInstall({
13838
+ workPath,
13839
+ rootDir,
13840
+ venvPath,
13841
+ pythonPackage,
13842
+ pythonVersion,
13843
+ uv,
13844
+ uvCacheDir,
13845
+ lockCacheKey: "uv.lock",
13846
+ pythonPlatform: target.uvPlatform,
13847
+ // Install only the proxy's dependency group into the proxy venv;
13848
+ // the project itself is neither built nor installed.
13849
+ // If the group is absent the proxy has no extra deps — skip sync.
13850
+ extraSyncParams: "vercel.proxy" in (pythonPackage?.manifest?.data?.["dependency-groups"] ?? {}) ? { onlyGroup: "vercel.proxy", noInstallProject: true } : void 0
13851
+ })
13852
+ );
13853
+ const pipPlatformArgs = target.uvPlatform ? ["--python-platform", target.uvPlatform] : [];
13854
+ await installInjectedPackage({
13855
+ name: "vercel-runtime",
13856
+ requirement: `vercel-runtime==${VERCEL_RUNTIME_VERSION}`,
13857
+ envOverride: process.env.VERCEL_RUNTIME_PYTHON,
13858
+ allowLocalSource: true,
13859
+ uv,
13860
+ venvPath,
13861
+ projectDir,
13862
+ pipPlatformArgs
13863
+ });
13864
+ const projectName = pythonPackage?.manifest?.data?.project?.name;
13865
+ const compileAllEnabled = shouldCompileAll({
13866
+ isDev: meta.isDev ?? false,
13867
+ hasCustomCommand: false
13868
+ });
13869
+ const pythonEnv = createVenvEnv(venvPath, process.env, uvCacheDir);
13870
+ const functionConfig = getMatchingFunction(
13871
+ config,
13872
+ entrypoint
13873
+ )?.functionConfig;
13874
+ const includeFilesPatterns = [
13875
+ ...normalizeGlobs(config?.includeFiles),
13876
+ ...normalizeGlobs(functionConfig?.includeFiles)
13877
+ ];
13878
+ const excludeFilesPatterns = [
13879
+ ...normalizeGlobs(config?.excludeFiles),
13880
+ ...normalizeGlobs(functionConfig?.excludeFiles)
13881
+ ];
13882
+ const initialFiles = {};
13883
+ for (const pattern of includeFilesPatterns) {
13884
+ Object.assign(initialFiles, await (0, import_build_utils24.glob)(pattern, workPath));
13885
+ }
13886
+ const { pycachePrefix, vendorDir, files } = await packFunctionBundle({
13887
+ builderSpan,
13888
+ workPath,
13889
+ uvLockPath,
13890
+ uvProjectDir: projectDir,
13891
+ projectName,
13892
+ pythonVersion,
13893
+ hasCustomCommand: false,
13894
+ alwaysBundlePackages: [],
13895
+ initialFiles,
13896
+ additionalExcludes: excludeFilesPatterns,
13897
+ compileAllEnabled,
13898
+ compileEnv: pythonEnv,
13899
+ venvPath,
13900
+ entrypoint,
13901
+ importClosureContext: {
13902
+ frameworkSeeds: [],
13903
+ extraPythonPath: void 0,
13904
+ subscriberDeclarations: [],
13905
+ subscribers: [],
13906
+ workflows: [],
13907
+ workflowMode: "workers"
13908
+ },
13909
+ largeFunctionLabel: entrypoint
13910
+ });
13911
+ const moduleName = entrypointToModule(entrypoint);
13912
+ const variableName = proxyHandlerFunction;
13913
+ const handlerPyFilename = "vc__handler__python";
13914
+ const runtimeTrampoline = createRuntimeTrampoline({
13915
+ moduleName,
13916
+ entrypoint,
13917
+ vendorDir,
13918
+ variableName,
13919
+ extraEnv: []
13920
+ });
13921
+ files[`${handlerPyFilename}.py`] = new import_build_utils24.FileBlob({ data: runtimeTrampoline });
13922
+ const lambdaOptions = await getPythonLambdaOptions({ config, entrypoint });
13923
+ const output = new import_build_utils24.Lambda({
13924
+ files,
13925
+ handler: `${handlerPyFilename}.vc_handler`,
13926
+ runtime: pythonVersion.runtime,
13927
+ ...lambdaOptions,
13928
+ architecture: target.architecture,
13929
+ environment: {
13930
+ PYTHONPATH: vendorDir,
13931
+ PYTHONDONTWRITEBYTECODE: "1",
13932
+ ...pycachePrefix ? { PYTHONPYCACHEPREFIX: pycachePrefix } : {}
13933
+ },
13934
+ supportsResponseStreaming: true
13935
+ });
13936
+ const matcher = (0, import_build_utils25.resolveMiddlewareMatcher)(
13937
+ config.middlewareMatcher,
13938
+ void 0,
13939
+ entrypoint
13940
+ );
13941
+ const src = (0, import_build_utils25.getRegExpFromMatchers)(matcher);
13942
+ const middlewareRawSrc = !matcher ? [] : Array.isArray(matcher) ? [...matcher] : [matcher];
13943
+ return {
13944
+ resultVersion: 3,
13945
+ result: {
13946
+ output,
13947
+ routes: [
13948
+ {
13949
+ src,
13950
+ middlewareRawSrc,
13951
+ middlewarePath: entrypoint.replace(/\.py$/i, ""),
13952
+ continue: true,
13953
+ override: true
13954
+ }
13955
+ ]
13956
+ }
13957
+ };
13958
+ }
13789
13959
  var build = async ({
13790
13960
  workPath,
13791
13961
  repoRootPath,
@@ -13797,14 +13967,19 @@ var build = async ({
13797
13967
  service,
13798
13968
  registerPreDeploy
13799
13969
  }) => {
13800
- if (config?.middleware === true) {
13801
- throw new import_build_utils24.NowBuildError({
13802
- code: "PYTHON_PROXY_NOT_IMPLEMENTED",
13803
- message: "Python proxy middleware is not yet supported."
13804
- });
13805
- }
13806
13970
  let entrypoint = rawEntrypoint === "<detect>" ? void 0 : rawEntrypoint;
13807
13971
  const builderSpan = parentSpan ?? new import_build_utils24.Span({ name: "vc.builder" });
13972
+ if (config?.middleware === true && entrypoint) {
13973
+ return buildProxyMiddleware({
13974
+ workPath,
13975
+ repoRootPath,
13976
+ files: originalFiles,
13977
+ entrypoint,
13978
+ config,
13979
+ meta,
13980
+ builderSpan
13981
+ });
13982
+ }
13808
13983
  const isPyprojectEntrypoint = entrypoint !== void 0 && (0, import_path21.basename)(entrypoint) === "pyproject.toml";
13809
13984
  if (isPyprojectEntrypoint && entrypoint !== "pyproject.toml") {
13810
13985
  throw new import_build_utils24.NowBuildError({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "15.0.0",
3
+ "version": "16.0.0",
4
4
  "main": "./dist/index.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -17,7 +17,7 @@
17
17
  "@vercel/python-analysis": "0.14.0"
18
18
  },
19
19
  "peerDependencies": {
20
- "@vercel/build-utils": "14.11.0"
20
+ "@vercel/build-utils": "14.12.0"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@renovatebot/pep440": "4.2.1",
@@ -38,7 +38,7 @@
38
38
  "smol-toml": "1.5.2",
39
39
  "vitest": "4.1.10",
40
40
  "which": "3.0.0",
41
- "@vercel/build-utils": "14.11.0",
41
+ "@vercel/build-utils": "14.12.0",
42
42
  "@vercel/error-utils": "2.2.1",
43
43
  "@vercel/python-runtime": "0.23.0"
44
44
  },