@vercel/python 6.19.0 → 6.20.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 +185 -138
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -2872,7 +2872,7 @@ var import_util2 = require("util");
2872
2872
  var import_path10 = require("path");
2873
2873
 
2874
2874
  // src/package-versions.ts
2875
- var VERCEL_RUNTIME_VERSION = "0.5.3";
2875
+ var VERCEL_RUNTIME_VERSION = "0.5.4";
2876
2876
 
2877
2877
  // src/index.ts
2878
2878
  var import_build_utils12 = require("@vercel/build-utils");
@@ -2957,7 +2957,7 @@ var UvRunner = class {
2957
2957
  );
2958
2958
  }
2959
2959
  async sync(options) {
2960
- const { venvPath, projectDir, locked, frozen, noBuild } = options;
2960
+ const { venvPath, projectDir, locked, frozen, noBuild, noInstallProject } = options;
2961
2961
  const args = ["sync", "--active", "--no-dev", "--link-mode", "copy"];
2962
2962
  if (frozen) {
2963
2963
  args.push("--frozen");
@@ -2967,6 +2967,9 @@ var UvRunner = class {
2967
2967
  if (noBuild) {
2968
2968
  args.push("--no-build");
2969
2969
  }
2970
+ if (noInstallProject) {
2971
+ args.push("--no-install-project");
2972
+ }
2970
2973
  args.push("--no-editable");
2971
2974
  await this.runUvCmd(args, projectDir, venvPath);
2972
2975
  }
@@ -3930,7 +3933,11 @@ To resolve this, either:
3930
3933
  action: "Learn More"
3931
3934
  });
3932
3935
  }
3933
- return { runtimeInstallEnabled, allVendorFiles: this.allVendorFiles };
3936
+ return {
3937
+ runtimeInstallEnabled,
3938
+ allVendorFiles: this.allVendorFiles,
3939
+ totalBundleSize: this.totalBundleSize
3940
+ };
3934
3941
  }
3935
3942
  /**
3936
3943
  * Generate the optimally-packed Lambda bundle.
@@ -4884,6 +4891,16 @@ If you are using a virtual environment, activate it before running "vercel dev",
4884
4891
  var import_build_utils11 = require("@vercel/build-utils");
4885
4892
  var import_python_analysis5 = require("@vercel/python-analysis");
4886
4893
 
4894
+ // src/quirks/matplotlib.ts
4895
+ var matplotlibQuirk = {
4896
+ dependency: "matplotlib",
4897
+ async run() {
4898
+ return {
4899
+ env: { MPLCONFIGDIR: "/tmp" }
4900
+ };
4901
+ }
4902
+ };
4903
+
4887
4904
  // src/quirks/litellm.ts
4888
4905
  var import_fs6 = __toESM(require("fs"));
4889
4906
  var import_path8 = require("path");
@@ -5232,7 +5249,7 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
5232
5249
  };
5233
5250
 
5234
5251
  // src/quirks/index.ts
5235
- var quirks = [litellmQuirk, prismaQuirk];
5252
+ var quirks = [litellmQuirk, prismaQuirk, matplotlibQuirk];
5236
5253
  function toposortQuirks(activated) {
5237
5254
  const nameToQuirk = /* @__PURE__ */ new Map();
5238
5255
  for (const q of activated) {
@@ -5360,8 +5377,10 @@ var build = async ({
5360
5377
  files: originalFiles,
5361
5378
  entrypoint,
5362
5379
  meta = {},
5363
- config
5380
+ config,
5381
+ span: parentSpan
5364
5382
  }) => {
5383
+ const builderSpan = parentSpan ?? new import_build_utils12.Span({ name: "vc.builder" });
5365
5384
  const framework = config?.framework;
5366
5385
  let spawnEnv;
5367
5386
  let projectInstallCommand;
@@ -5423,67 +5442,74 @@ var build = async ({
5423
5442
  workPath,
5424
5443
  fsFiles
5425
5444
  });
5426
- let declaredPythonVersion;
5427
- if (pythonVersionFileDir) {
5428
- try {
5429
- const content = await readFile2(
5430
- (0, import_path10.join)(pythonVersionFileDir, ".python-version"),
5431
- "utf8"
5432
- );
5433
- const version2 = parsePythonVersionFile(content);
5434
- if (version2) {
5435
- declaredPythonVersion = { version: version2, source: ".python-version" };
5436
- (0, import_build_utils12.debug)(`Found Python version ${version2} in .python-version`);
5445
+ const { pythonVersion, declaredPythonVersion } = await builderSpan.child("vc.builder.python.version").trace(async (versionSpan) => {
5446
+ let declared;
5447
+ if (pythonVersionFileDir) {
5448
+ try {
5449
+ const content = await readFile2(
5450
+ (0, import_path10.join)(pythonVersionFileDir, ".python-version"),
5451
+ "utf8"
5452
+ );
5453
+ const version2 = parsePythonVersionFile(content);
5454
+ if (version2) {
5455
+ declared = { version: version2, source: ".python-version" };
5456
+ (0, import_build_utils12.debug)(`Found Python version ${version2} in .python-version`);
5457
+ }
5458
+ } catch (err) {
5459
+ (0, import_build_utils12.debug)("Failed to read .python-version file", err);
5437
5460
  }
5438
- } catch (err) {
5439
- (0, import_build_utils12.debug)("Failed to read .python-version file", err);
5440
- }
5441
- }
5442
- if (!declaredPythonVersion && pyprojectDir) {
5443
- let requiresPython;
5444
- try {
5445
- const pyproject = await (0, import_build_utils13.readConfigFile)((0, import_path10.join)(pyprojectDir, "pyproject.toml"));
5446
- requiresPython = pyproject?.project?.["requires-python"];
5447
- } catch (err) {
5448
- (0, import_build_utils12.debug)("Failed to parse pyproject.toml", err);
5449
- }
5450
- if (typeof requiresPython === "string" && requiresPython.trim()) {
5451
- declaredPythonVersion = {
5452
- version: requiresPython.trim(),
5453
- source: "pyproject.toml"
5454
- };
5455
- (0, import_build_utils12.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
5456
5461
  }
5457
- }
5458
- if (!declaredPythonVersion && pipfileLockDir) {
5459
- let lock = {};
5460
- const pipfileLockPath = (0, import_path10.join)(pipfileLockDir, "Pipfile.lock");
5461
- try {
5462
- const pipfileLockContent = await readFile2(pipfileLockPath, "utf8");
5462
+ if (!declared && pyprojectDir) {
5463
+ let requiresPython;
5463
5464
  try {
5464
- lock = JSON.parse(pipfileLockContent);
5465
+ const pyproject = await (0, import_build_utils13.readConfigFile)((0, import_path10.join)(pyprojectDir, "pyproject.toml"));
5466
+ requiresPython = pyproject?.project?.["requires-python"];
5465
5467
  } catch (err) {
5466
- console.log(
5467
- `Failed to parse "Pipfile.lock". File content:
5468
- ${pipfileLockContent}`
5469
- );
5470
- throw err;
5468
+ (0, import_build_utils12.debug)("Failed to parse pyproject.toml", err);
5469
+ }
5470
+ if (typeof requiresPython === "string" && requiresPython.trim()) {
5471
+ declared = {
5472
+ version: requiresPython.trim(),
5473
+ source: "pyproject.toml"
5474
+ };
5475
+ (0, import_build_utils12.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
5471
5476
  }
5472
- } catch (err) {
5473
- throw new import_build_utils12.NowBuildError({
5474
- code: "INVALID_PIPFILE_LOCK",
5475
- message: "Unable to parse Pipfile.lock"
5476
- });
5477
5477
  }
5478
- const pyFromLock = lock?._meta?.requires?.python_version;
5479
- if (pyFromLock) {
5480
- declaredPythonVersion = { version: pyFromLock, source: "Pipfile.lock" };
5481
- (0, import_build_utils12.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
5478
+ if (!declared && pipfileLockDir) {
5479
+ let lock = {};
5480
+ const pipfileLockPath = (0, import_path10.join)(pipfileLockDir, "Pipfile.lock");
5481
+ try {
5482
+ const pipfileLockContent = await readFile2(pipfileLockPath, "utf8");
5483
+ try {
5484
+ lock = JSON.parse(pipfileLockContent);
5485
+ } catch (err) {
5486
+ console.log(
5487
+ `Failed to parse "Pipfile.lock". File content:
5488
+ ${pipfileLockContent}`
5489
+ );
5490
+ throw err;
5491
+ }
5492
+ } catch (err) {
5493
+ throw new import_build_utils12.NowBuildError({
5494
+ code: "INVALID_PIPFILE_LOCK",
5495
+ message: "Unable to parse Pipfile.lock"
5496
+ });
5497
+ }
5498
+ const pyFromLock = lock?._meta?.requires?.python_version;
5499
+ if (pyFromLock) {
5500
+ declared = { version: pyFromLock, source: "Pipfile.lock" };
5501
+ (0, import_build_utils12.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
5502
+ }
5482
5503
  }
5483
- }
5484
- const pythonVersion = getSupportedPythonVersion({
5485
- isDev: meta.isDev,
5486
- declaredPythonVersion
5504
+ const resolved = getSupportedPythonVersion({
5505
+ isDev: meta.isDev,
5506
+ declaredPythonVersion: declared
5507
+ });
5508
+ versionSpan.setAttributes({
5509
+ "python.version": resolved.version,
5510
+ "python.versionSource": declared?.source
5511
+ });
5512
+ return { pythonVersion: resolved, declaredPythonVersion: declared };
5487
5513
  });
5488
5514
  const selectedVersionTuple = parseVersionTuple(pythonVersion.version);
5489
5515
  const defaultVersionTuple = parseVersionTuple(DEFAULT_PYTHON_VERSION);
@@ -5497,9 +5523,11 @@ ${pipfileLockContent}`
5497
5523
  }
5498
5524
  fsFiles = await (0, import_build_utils12.glob)("**", workPath);
5499
5525
  const venvPath = (0, import_path10.join)(workPath, ".vercel", "python", ".venv");
5500
- await ensureVenv({
5501
- pythonPath: pythonVersion.pythonPath,
5502
- venvPath
5526
+ await builderSpan.child("vc.builder.python.venv").trace(async () => {
5527
+ await ensureVenv({
5528
+ pythonPath: pythonVersion.pythonPath,
5529
+ venvPath
5530
+ });
5503
5531
  });
5504
5532
  if ((0, import_build_utils12.isPythonFramework)(framework)) {
5505
5533
  const {
@@ -5530,26 +5558,6 @@ ${pipfileLockContent}`
5530
5558
  const pythonEnv = createVenvEnv(venvPath, baseEnv);
5531
5559
  pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
5532
5560
  let assumeDepsInstalled = false;
5533
- if (projectInstallCommand) {
5534
- console.log(`Running "install" command: \`${projectInstallCommand}\`...`);
5535
- await (0, import_build_utils12.execCommand)(projectInstallCommand, {
5536
- env: pythonEnv,
5537
- cwd: workPath
5538
- });
5539
- assumeDepsInstalled = true;
5540
- hasCustomCommand = true;
5541
- } else {
5542
- assumeDepsInstalled = await runPyprojectScript(
5543
- workPath,
5544
- ["vercel-install", "now-install", "install"],
5545
- pythonEnv,
5546
- /* useUserVirtualEnv */
5547
- false
5548
- );
5549
- if (assumeDepsInstalled) {
5550
- hasCustomCommand = true;
5551
- }
5552
- }
5553
5561
  let uv;
5554
5562
  try {
5555
5563
  const uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
@@ -5565,62 +5573,93 @@ ${pipfileLockContent}`
5565
5573
  let uvProjectDir = null;
5566
5574
  let projectName;
5567
5575
  let noBuildCheckFailed = false;
5568
- if (!assumeDepsInstalled) {
5569
- const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
5570
- workPath,
5571
- entryDirectory,
5572
- repoRootPath,
5573
- pythonVersion: pythonVersion.version,
5574
- uv,
5575
- generateLockFile: true,
5576
- requireBinaryWheels: false
5577
- });
5578
- uvLockPath = lockPath;
5579
- uvProjectDir = projectDir;
5580
- const installInfo = await detectInstallSource({
5581
- workPath,
5582
- entryDirectory,
5583
- repoRootPath
5584
- });
5585
- projectName = installInfo.pythonPackage?.manifest?.data?.project?.name;
5586
- if (lockFileProvidedByUser) {
5587
- try {
5588
- await uv.sync({
5589
- venvPath,
5590
- projectDir,
5591
- frozen: true,
5592
- noBuild: true
5593
- });
5594
- } catch (err) {
5595
- noBuildCheckFailed = true;
5596
- (0, import_build_utils12.debug)(
5597
- `--no-build check failed: ${err instanceof Error ? err.message : String(err)}`
5598
- );
5599
- }
5600
- }
5601
- await uv.sync({
5602
- venvPath,
5603
- projectDir,
5604
- frozen: lockFileProvidedByUser,
5605
- locked: !lockFileProvidedByUser
5606
- });
5607
- }
5608
- if ((0, import_build_utils12.isPythonFramework)(framework)) {
5609
- const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
5610
- config?.buildCommand;
5611
- if (projectBuildCommand) {
5612
- console.log(`Running "${projectBuildCommand}"`);
5613
- await (0, import_build_utils12.execCommand)(projectBuildCommand, {
5576
+ await builderSpan.child(import_build_utils12.BUILDER_INSTALLER_STEP, {
5577
+ installCommand: projectInstallCommand || void 0
5578
+ }).trace(async () => {
5579
+ if (projectInstallCommand) {
5580
+ console.log(
5581
+ `Running "install" command: \`${projectInstallCommand}\`...`
5582
+ );
5583
+ await (0, import_build_utils12.execCommand)(projectInstallCommand, {
5614
5584
  env: pythonEnv,
5615
5585
  cwd: workPath
5616
5586
  });
5587
+ assumeDepsInstalled = true;
5588
+ hasCustomCommand = true;
5617
5589
  } else {
5618
- await runPyprojectScript(
5590
+ assumeDepsInstalled = await runPyprojectScript(
5619
5591
  workPath,
5620
- ["vercel-build", "now-build", "build"],
5621
- pythonEnv
5592
+ ["vercel-install", "now-install", "install"],
5593
+ pythonEnv,
5594
+ /* useUserVirtualEnv */
5595
+ false
5622
5596
  );
5597
+ if (assumeDepsInstalled) {
5598
+ hasCustomCommand = true;
5599
+ }
5600
+ }
5601
+ if (!assumeDepsInstalled) {
5602
+ const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
5603
+ workPath,
5604
+ entryDirectory,
5605
+ repoRootPath,
5606
+ pythonVersion: pythonVersion.version,
5607
+ uv,
5608
+ generateLockFile: true,
5609
+ requireBinaryWheels: false
5610
+ });
5611
+ uvLockPath = lockPath;
5612
+ uvProjectDir = projectDir;
5613
+ const installInfo = await detectInstallSource({
5614
+ workPath,
5615
+ entryDirectory,
5616
+ repoRootPath
5617
+ });
5618
+ projectName = installInfo.pythonPackage?.manifest?.data?.project?.name;
5619
+ if (lockFileProvidedByUser) {
5620
+ try {
5621
+ await uv.sync({
5622
+ venvPath,
5623
+ projectDir,
5624
+ frozen: true,
5625
+ noBuild: true,
5626
+ noInstallProject: true
5627
+ });
5628
+ } catch (err) {
5629
+ noBuildCheckFailed = true;
5630
+ (0, import_build_utils12.debug)(
5631
+ `--no-build check failed: ${err instanceof Error ? err.message : String(err)}`
5632
+ );
5633
+ }
5634
+ }
5635
+ await uv.sync({
5636
+ venvPath,
5637
+ projectDir,
5638
+ frozen: lockFileProvidedByUser,
5639
+ locked: !lockFileProvidedByUser
5640
+ });
5623
5641
  }
5642
+ });
5643
+ if ((0, import_build_utils12.isPythonFramework)(framework)) {
5644
+ const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
5645
+ config?.buildCommand;
5646
+ await builderSpan.child(import_build_utils12.BUILDER_COMPILE_STEP, {
5647
+ buildCommand: projectBuildCommand || void 0
5648
+ }).trace(async () => {
5649
+ if (projectBuildCommand) {
5650
+ console.log(`Running "${projectBuildCommand}"`);
5651
+ await (0, import_build_utils12.execCommand)(projectBuildCommand, {
5652
+ env: pythonEnv,
5653
+ cwd: workPath
5654
+ });
5655
+ } else {
5656
+ await runPyprojectScript(
5657
+ workPath,
5658
+ ["vercel-build", "now-build", "build"],
5659
+ pythonEnv
5660
+ );
5661
+ }
5662
+ });
5624
5663
  }
5625
5664
  const runtimeDep = baseEnv.VERCEL_RUNTIME_PYTHON || `vercel-runtime==${VERCEL_RUNTIME_VERSION}`;
5626
5665
  (0, import_build_utils12.debug)(`Installing ${runtimeDep}`);
@@ -5715,14 +5754,22 @@ from vercel_runtime.vc_init import vc_handler
5715
5754
  hasCustomCommand,
5716
5755
  alwaysBundlePackages: quirksResult.alwaysBundlePackages
5717
5756
  });
5718
- const { runtimeInstallEnabled, allVendorFiles } = await depExternalizer.analyze(files);
5719
- if (runtimeInstallEnabled) {
5720
- await depExternalizer.generateBundle(files);
5721
- } else {
5722
- for (const [p, f] of Object.entries(allVendorFiles)) {
5723
- files[p] = f;
5757
+ await builderSpan.child("vc.builder.python.bundle").trace(async (bundleSpan) => {
5758
+ const depAnalysis = await depExternalizer.analyze(files);
5759
+ bundleSpan.setAttributes({
5760
+ "python.bundle.totalSizeBytes": String(depAnalysis.totalBundleSize),
5761
+ "python.bundle.runtimeInstallEnabled": String(
5762
+ depAnalysis.runtimeInstallEnabled
5763
+ )
5764
+ });
5765
+ if (depAnalysis.runtimeInstallEnabled) {
5766
+ await depExternalizer.generateBundle(files);
5767
+ } else {
5768
+ for (const [p, f] of Object.entries(depAnalysis.allVendorFiles)) {
5769
+ files[p] = f;
5770
+ }
5724
5771
  }
5725
- }
5772
+ });
5726
5773
  const handlerPyFilename = "vc__handler__python";
5727
5774
  files[`${handlerPyFilename}.py`] = new import_build_utils12.FileBlob({ data: runtimeTrampoline });
5728
5775
  if (config.framework === "fasthtml") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vercel/python",
3
- "version": "6.19.0",
3
+ "version": "6.20.0",
4
4
  "main": "./dist/index.js",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
@@ -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.6.1",
38
+ "@vercel/build-utils": "13.6.2",
39
39
  "@vercel/error-utils": "2.0.3",
40
- "@vercel/python-runtime": "0.5.3"
40
+ "@vercel/python-runtime": "0.5.4"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "node ../../utils/build-builder.mjs",