@vercel/python 6.19.0 → 6.20.1

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 +200 -139
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -2872,7 +2872,8 @@ 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.5";
2876
+ var VERCEL_WORKERS_VERSION = "0.0.11";
2876
2877
 
2877
2878
  // src/index.ts
2878
2879
  var import_build_utils12 = require("@vercel/build-utils");
@@ -2957,7 +2958,7 @@ var UvRunner = class {
2957
2958
  );
2958
2959
  }
2959
2960
  async sync(options) {
2960
- const { venvPath, projectDir, locked, frozen, noBuild } = options;
2961
+ const { venvPath, projectDir, locked, frozen, noBuild, noInstallProject } = options;
2961
2962
  const args = ["sync", "--active", "--no-dev", "--link-mode", "copy"];
2962
2963
  if (frozen) {
2963
2964
  args.push("--frozen");
@@ -2967,6 +2968,9 @@ var UvRunner = class {
2967
2968
  if (noBuild) {
2968
2969
  args.push("--no-build");
2969
2970
  }
2971
+ if (noInstallProject) {
2972
+ args.push("--no-install-project");
2973
+ }
2970
2974
  args.push("--no-editable");
2971
2975
  await this.runUvCmd(args, projectDir, venvPath);
2972
2976
  }
@@ -3930,7 +3934,11 @@ To resolve this, either:
3930
3934
  action: "Learn More"
3931
3935
  });
3932
3936
  }
3933
- return { runtimeInstallEnabled, allVendorFiles: this.allVendorFiles };
3937
+ return {
3938
+ runtimeInstallEnabled,
3939
+ allVendorFiles: this.allVendorFiles,
3940
+ totalBundleSize: this.totalBundleSize
3941
+ };
3934
3942
  }
3935
3943
  /**
3936
3944
  * Generate the optimally-packed Lambda bundle.
@@ -4884,6 +4892,16 @@ If you are using a virtual environment, activate it before running "vercel dev",
4884
4892
  var import_build_utils11 = require("@vercel/build-utils");
4885
4893
  var import_python_analysis5 = require("@vercel/python-analysis");
4886
4894
 
4895
+ // src/quirks/matplotlib.ts
4896
+ var matplotlibQuirk = {
4897
+ dependency: "matplotlib",
4898
+ async run() {
4899
+ return {
4900
+ env: { MPLCONFIGDIR: "/tmp" }
4901
+ };
4902
+ }
4903
+ };
4904
+
4887
4905
  // src/quirks/litellm.ts
4888
4906
  var import_fs6 = __toESM(require("fs"));
4889
4907
  var import_path8 = require("path");
@@ -5232,7 +5250,7 @@ echo "OpenSSL ${RUNTIME_OPENSSL_VERSION}.0 1 Jan 2024 (Library: OpenSSL ${RUNTIM
5232
5250
  };
5233
5251
 
5234
5252
  // src/quirks/index.ts
5235
- var quirks = [litellmQuirk, prismaQuirk];
5253
+ var quirks = [litellmQuirk, prismaQuirk, matplotlibQuirk];
5236
5254
  function toposortQuirks(activated) {
5237
5255
  const nameToQuirk = /* @__PURE__ */ new Map();
5238
5256
  for (const q of activated) {
@@ -5360,9 +5378,12 @@ var build = async ({
5360
5378
  files: originalFiles,
5361
5379
  entrypoint,
5362
5380
  meta = {},
5363
- config
5381
+ config,
5382
+ span: parentSpan
5364
5383
  }) => {
5384
+ const builderSpan = parentSpan ?? new import_build_utils12.Span({ name: "vc.builder" });
5365
5385
  const framework = config?.framework;
5386
+ const shouldInstallVercelWorkers = config?.hasWorkerServices === true;
5366
5387
  let spawnEnv;
5367
5388
  let projectInstallCommand;
5368
5389
  let hasCustomCommand = false;
@@ -5423,67 +5444,74 @@ var build = async ({
5423
5444
  workPath,
5424
5445
  fsFiles
5425
5446
  });
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`);
5447
+ const { pythonVersion, declaredPythonVersion } = await builderSpan.child("vc.builder.python.version").trace(async (versionSpan) => {
5448
+ let declared;
5449
+ if (pythonVersionFileDir) {
5450
+ try {
5451
+ const content = await readFile2(
5452
+ (0, import_path10.join)(pythonVersionFileDir, ".python-version"),
5453
+ "utf8"
5454
+ );
5455
+ const version2 = parsePythonVersionFile(content);
5456
+ if (version2) {
5457
+ declared = { version: version2, source: ".python-version" };
5458
+ (0, import_build_utils12.debug)(`Found Python version ${version2} in .python-version`);
5459
+ }
5460
+ } catch (err) {
5461
+ (0, import_build_utils12.debug)("Failed to read .python-version file", err);
5437
5462
  }
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
5463
  }
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");
5464
+ if (!declared && pyprojectDir) {
5465
+ let requiresPython;
5463
5466
  try {
5464
- lock = JSON.parse(pipfileLockContent);
5467
+ const pyproject = await (0, import_build_utils13.readConfigFile)((0, import_path10.join)(pyprojectDir, "pyproject.toml"));
5468
+ requiresPython = pyproject?.project?.["requires-python"];
5465
5469
  } catch (err) {
5466
- console.log(
5467
- `Failed to parse "Pipfile.lock". File content:
5468
- ${pipfileLockContent}`
5469
- );
5470
- throw err;
5470
+ (0, import_build_utils12.debug)("Failed to parse pyproject.toml", err);
5471
+ }
5472
+ if (typeof requiresPython === "string" && requiresPython.trim()) {
5473
+ declared = {
5474
+ version: requiresPython.trim(),
5475
+ source: "pyproject.toml"
5476
+ };
5477
+ (0, import_build_utils12.debug)(`Found requires-python "${requiresPython}" in pyproject.toml`);
5471
5478
  }
5472
- } catch (err) {
5473
- throw new import_build_utils12.NowBuildError({
5474
- code: "INVALID_PIPFILE_LOCK",
5475
- message: "Unable to parse Pipfile.lock"
5476
- });
5477
5479
  }
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`);
5480
+ if (!declared && pipfileLockDir) {
5481
+ let lock = {};
5482
+ const pipfileLockPath = (0, import_path10.join)(pipfileLockDir, "Pipfile.lock");
5483
+ try {
5484
+ const pipfileLockContent = await readFile2(pipfileLockPath, "utf8");
5485
+ try {
5486
+ lock = JSON.parse(pipfileLockContent);
5487
+ } catch (err) {
5488
+ console.log(
5489
+ `Failed to parse "Pipfile.lock". File content:
5490
+ ${pipfileLockContent}`
5491
+ );
5492
+ throw err;
5493
+ }
5494
+ } catch (err) {
5495
+ throw new import_build_utils12.NowBuildError({
5496
+ code: "INVALID_PIPFILE_LOCK",
5497
+ message: "Unable to parse Pipfile.lock"
5498
+ });
5499
+ }
5500
+ const pyFromLock = lock?._meta?.requires?.python_version;
5501
+ if (pyFromLock) {
5502
+ declared = { version: pyFromLock, source: "Pipfile.lock" };
5503
+ (0, import_build_utils12.debug)(`Found Python version ${pyFromLock} in Pipfile.lock`);
5504
+ }
5482
5505
  }
5483
- }
5484
- const pythonVersion = getSupportedPythonVersion({
5485
- isDev: meta.isDev,
5486
- declaredPythonVersion
5506
+ const resolved = getSupportedPythonVersion({
5507
+ isDev: meta.isDev,
5508
+ declaredPythonVersion: declared
5509
+ });
5510
+ versionSpan.setAttributes({
5511
+ "python.version": resolved.version,
5512
+ "python.versionSource": declared?.source
5513
+ });
5514
+ return { pythonVersion: resolved, declaredPythonVersion: declared };
5487
5515
  });
5488
5516
  const selectedVersionTuple = parseVersionTuple(pythonVersion.version);
5489
5517
  const defaultVersionTuple = parseVersionTuple(DEFAULT_PYTHON_VERSION);
@@ -5497,9 +5525,11 @@ ${pipfileLockContent}`
5497
5525
  }
5498
5526
  fsFiles = await (0, import_build_utils12.glob)("**", workPath);
5499
5527
  const venvPath = (0, import_path10.join)(workPath, ".vercel", "python", ".venv");
5500
- await ensureVenv({
5501
- pythonPath: pythonVersion.pythonPath,
5502
- venvPath
5528
+ await builderSpan.child("vc.builder.python.venv").trace(async () => {
5529
+ await ensureVenv({
5530
+ pythonPath: pythonVersion.pythonPath,
5531
+ venvPath
5532
+ });
5503
5533
  });
5504
5534
  if ((0, import_build_utils12.isPythonFramework)(framework)) {
5505
5535
  const {
@@ -5530,26 +5560,6 @@ ${pipfileLockContent}`
5530
5560
  const pythonEnv = createVenvEnv(venvPath, baseEnv);
5531
5561
  pythonEnv.VERCEL_PYTHON_VENV_PATH = venvPath;
5532
5562
  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
5563
  let uv;
5554
5564
  try {
5555
5565
  const uvPath = await getUvBinaryOrInstall(pythonVersion.pythonPath);
@@ -5565,62 +5575,93 @@ ${pipfileLockContent}`
5565
5575
  let uvProjectDir = null;
5566
5576
  let projectName;
5567
5577
  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, {
5578
+ await builderSpan.child(import_build_utils12.BUILDER_INSTALLER_STEP, {
5579
+ installCommand: projectInstallCommand || void 0
5580
+ }).trace(async () => {
5581
+ if (projectInstallCommand) {
5582
+ console.log(
5583
+ `Running "install" command: \`${projectInstallCommand}\`...`
5584
+ );
5585
+ await (0, import_build_utils12.execCommand)(projectInstallCommand, {
5614
5586
  env: pythonEnv,
5615
5587
  cwd: workPath
5616
5588
  });
5589
+ assumeDepsInstalled = true;
5590
+ hasCustomCommand = true;
5617
5591
  } else {
5618
- await runPyprojectScript(
5592
+ assumeDepsInstalled = await runPyprojectScript(
5619
5593
  workPath,
5620
- ["vercel-build", "now-build", "build"],
5621
- pythonEnv
5594
+ ["vercel-install", "now-install", "install"],
5595
+ pythonEnv,
5596
+ /* useUserVirtualEnv */
5597
+ false
5622
5598
  );
5599
+ if (assumeDepsInstalled) {
5600
+ hasCustomCommand = true;
5601
+ }
5602
+ }
5603
+ if (!assumeDepsInstalled) {
5604
+ const { projectDir, lockPath, lockFileProvidedByUser } = await ensureUvProject({
5605
+ workPath,
5606
+ entryDirectory,
5607
+ repoRootPath,
5608
+ pythonVersion: pythonVersion.version,
5609
+ uv,
5610
+ generateLockFile: true,
5611
+ requireBinaryWheels: false
5612
+ });
5613
+ uvLockPath = lockPath;
5614
+ uvProjectDir = projectDir;
5615
+ const installInfo = await detectInstallSource({
5616
+ workPath,
5617
+ entryDirectory,
5618
+ repoRootPath
5619
+ });
5620
+ projectName = installInfo.pythonPackage?.manifest?.data?.project?.name;
5621
+ if (lockFileProvidedByUser) {
5622
+ try {
5623
+ await uv.sync({
5624
+ venvPath,
5625
+ projectDir,
5626
+ frozen: true,
5627
+ noBuild: true,
5628
+ noInstallProject: true
5629
+ });
5630
+ } catch (err) {
5631
+ noBuildCheckFailed = true;
5632
+ (0, import_build_utils12.debug)(
5633
+ `--no-build check failed: ${err instanceof Error ? err.message : String(err)}`
5634
+ );
5635
+ }
5636
+ }
5637
+ await uv.sync({
5638
+ venvPath,
5639
+ projectDir,
5640
+ frozen: lockFileProvidedByUser,
5641
+ locked: !lockFileProvidedByUser
5642
+ });
5623
5643
  }
5644
+ });
5645
+ if ((0, import_build_utils12.isPythonFramework)(framework)) {
5646
+ const projectBuildCommand = config?.projectSettings?.buildCommand ?? // fallback if provided directly on config (some callers set this)
5647
+ config?.buildCommand;
5648
+ await builderSpan.child(import_build_utils12.BUILDER_COMPILE_STEP, {
5649
+ buildCommand: projectBuildCommand || void 0
5650
+ }).trace(async () => {
5651
+ if (projectBuildCommand) {
5652
+ console.log(`Running "${projectBuildCommand}"`);
5653
+ await (0, import_build_utils12.execCommand)(projectBuildCommand, {
5654
+ env: pythonEnv,
5655
+ cwd: workPath
5656
+ });
5657
+ } else {
5658
+ await runPyprojectScript(
5659
+ workPath,
5660
+ ["vercel-build", "now-build", "build"],
5661
+ pythonEnv
5662
+ );
5663
+ }
5664
+ });
5624
5665
  }
5625
5666
  const runtimeDep = baseEnv.VERCEL_RUNTIME_PYTHON || `vercel-runtime==${VERCEL_RUNTIME_VERSION}`;
5626
5667
  (0, import_build_utils12.debug)(`Installing ${runtimeDep}`);
@@ -5629,6 +5670,15 @@ ${pipfileLockContent}`
5629
5670
  projectDir: (0, import_path10.join)(workPath, entryDirectory),
5630
5671
  args: ["install", runtimeDep]
5631
5672
  });
5673
+ if (shouldInstallVercelWorkers) {
5674
+ const workersDep = baseEnv.VERCEL_WORKERS_PYTHON || `vercel-workers==${VERCEL_WORKERS_VERSION}`;
5675
+ (0, import_build_utils12.debug)(`Installing ${workersDep}`);
5676
+ await uv.pip({
5677
+ venvPath,
5678
+ projectDir: (0, import_path10.join)(workPath, entryDirectory),
5679
+ args: ["install", workersDep]
5680
+ });
5681
+ }
5632
5682
  const quirksResult = await runQuirks({ venvPath, pythonEnv, workPath });
5633
5683
  if (quirksResult.buildEnv) {
5634
5684
  Object.assign(pythonEnv, quirksResult.buildEnv);
@@ -5713,16 +5763,27 @@ from vercel_runtime.vc_init import vc_handler
5713
5763
  noBuildCheckFailed,
5714
5764
  pythonPath: pythonVersion.pythonPath,
5715
5765
  hasCustomCommand,
5716
- alwaysBundlePackages: quirksResult.alwaysBundlePackages
5766
+ alwaysBundlePackages: [
5767
+ ...quirksResult.alwaysBundlePackages,
5768
+ ...shouldInstallVercelWorkers ? ["vercel-workers", "vercel_workers"] : []
5769
+ ]
5717
5770
  });
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;
5771
+ await builderSpan.child("vc.builder.python.bundle").trace(async (bundleSpan) => {
5772
+ const depAnalysis = await depExternalizer.analyze(files);
5773
+ bundleSpan.setAttributes({
5774
+ "python.bundle.totalSizeBytes": String(depAnalysis.totalBundleSize),
5775
+ "python.bundle.runtimeInstallEnabled": String(
5776
+ depAnalysis.runtimeInstallEnabled
5777
+ )
5778
+ });
5779
+ if (depAnalysis.runtimeInstallEnabled) {
5780
+ await depExternalizer.generateBundle(files);
5781
+ } else {
5782
+ for (const [p, f] of Object.entries(depAnalysis.allVendorFiles)) {
5783
+ files[p] = f;
5784
+ }
5724
5785
  }
5725
- }
5786
+ });
5726
5787
  const handlerPyFilename = "vc__handler__python";
5727
5788
  files[`${handlerPyFilename}.py`] = new import_build_utils12.FileBlob({ data: runtimeTrampoline });
5728
5789
  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.1",
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",
39
- "@vercel/error-utils": "2.0.3",
40
- "@vercel/python-runtime": "0.5.3"
38
+ "@vercel/build-utils": "13.6.2",
39
+ "@vercel/python-runtime": "0.5.5",
40
+ "@vercel/error-utils": "2.0.3"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "node ../../utils/build-builder.mjs",