Repository: pantsbuild/pants
Pull request #22023: upgrade `packaging` to v24.2
Author: login: tdyas
Labels: name: category:internal
description: CI, fixes for not-yet-released features, etc.
Created: 2025-02-28T21:18:15Z | Merged: 2025-03-02T06:17:09Z

Upgrade `packaging` dependency to v24.2.


Diff:
diff --git a/3rdparty/python/requirements.txt b/3rdparty/python/requirements.txt
index b0095e4e3f1..4ec81721e90 100644
--- a/3rdparty/python/requirements.txt
+++ b/3rdparty/python/requirements.txt
@@ -10,7 +10,7 @@ fasteners==0.16.3
 freezegun==1.2.1
 ijson==3.2.3
 libcst==1.4.0
-packaging==21.3
+packaging==24.2
 pex==2.33.1
 psutil==5.9.8
 # This should be compatible with pytest.py, although it can be looser so that we don't
diff --git a/3rdparty/python/user_reqs.lock b/3rdparty/python/user_reqs.lock
index 664135b233c..a7745881a22 100644
--- a/3rdparty/python/user_reqs.lock
+++ b/3rdparty/python/user_reqs.lock
@@ -22,7 +22,7 @@
 //     "libcst==1.4.0",
 //     "mypy-typing-asserts==0.1.1",
 //     "node-semver==0.9.0",
-//     "packaging==21.3",
+//     "packaging==24.2",
 //     "pex==2.33.1",
 //     "psutil==5.9.8",
 //     "pydevd-pycharm==203.5419.8",
@@ -1005,21 +1005,19 @@
           "artifacts": [
             {
               "algorithm": "sha256",
-              "hash": "ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522",
-              "url": "https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl"
+              "hash": "09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759",
+              "url": "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl"
             },
             {
               "algorithm": "sha256",
-              "hash": "dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
-              "url": "https://files.pythonhosted.org/packages/df/9e/d1a7217f69310c1db8fdf8ab396229f55a699ce34a203691794c5d1cad0c/packaging-21.3.tar.gz"
+              "hash": "c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f",
+              "url": "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz"
             }
           ],
           "project_name": "packaging",
-          "requires_dists": [
-            "pyparsing!=3.0.5,>=2.0.2"
-          ],
-          "requires_python": ">=3.6",
-          "version": "21.3"
+          "requires_dists": [],
+          "requires_python": ">=3.8",
+          "version": "24.2"
         },
         {
           "artifacts": [
@@ -1336,27 +1334,6 @@
           "requires_python": ">=3.6",
           "version": "1.5.0"
         },
-        {
-          "artifacts": [
-            {
-              "algorithm": "sha256",
-              "hash": "506ff4f4386c4cec0590ec19e6302d3aedb992fdc02c761e90416f158dacf8e1",
-              "url": "https://files.pythonhosted.org/packages/1c/a7/c8a2d361bf89c0d9577c934ebb7421b25dc84bf3a8e3ac0a40aed9acc547/pyparsing-3.2.1-py3-none-any.whl"
-            },
-            {
-              "algorithm": "sha256",
-              "hash": "61980854fd66de3a90028d679a954d5f2623e83144b5afe5ee86f43d762e5f0a",
-              "url": "https://files.pythonhosted.org/packages/8b/1a/3544f4f299a47911c2ab3710f534e52fea62a633c96806995da5d25be4b2/pyparsing-3.2.1.tar.gz"
-            }
-          ],
-          "project_name": "pyparsing",
-          "requires_dists": [
-            "jinja2; extra == \"diagrams\"",
-            "railroad-diagrams; extra == \"diagrams\""
-          ],
-          "requires_python": ">=3.9",
-          "version": "3.2.1"
-        },
         {
           "artifacts": [
             {
@@ -2354,7 +2331,7 @@
     "libcst==1.4.0",
     "mypy-typing-asserts==0.1.1",
     "node-semver==0.9.0",
-    "packaging==21.3",
+    "packaging==24.2",
     "pex==2.33.1",
     "psutil==5.9.8",
     "pydevd-pycharm==203.5419.8",
diff --git a/docs/notes/2.26.x.md b/docs/notes/2.26.x.md
index 38a00445a72..e7acb5f35bc 100644
--- a/docs/notes/2.26.x.md
+++ b/docs/notes/2.26.x.md
@@ -90,6 +90,8 @@ A bug in the Django backend has been fixed so that a repo may have no Django app
 
 [Pytype](https://www.pantsbuild.org/stable/reference/subsystems/pytype) was updated to version 2024.9.13 - which is the [last to support Python 3.8 and Python 3.9](https://github.com/google/pytype/blob/main/CHANGELOG).
 
+The Python backend uses the PyPI `packaging` distribution to parse Python version numbers. In upgrading `packaging` from v21.3 to v24.2, support for parsing "legacy" Python versions was removed. We do not anticipate an issue here (since [PEP 440](https://peps.python.org/pep-0440/) has been around since 2013), but please contact the maintainers if an issue does arise.
+
 #### Shell
 
 The `experiemental_test_shell_command` target type learned several new features:
diff --git a/src/python/pants/backend/python/util_rules/lockfile_diff.py b/src/python/pants/backend/python/util_rules/lockfile_diff.py
index 6e78c0c88fc..c87c3f867af 100644
--- a/src/python/pants/backend/python/util_rules/lockfile_diff.py
+++ b/src/python/pants/backend/python/util_rules/lockfile_diff.py
@@ -8,14 +8,9 @@
 import logging
 from collections.abc import Mapping
 from dataclasses import dataclass
-from typing import TYPE_CHECKING, Any
+from typing import Any
 
-from packaging.version import parse
-
-if TYPE_CHECKING:
-    # We seem to get a version of `packaging` that doesn't have `LegacyVersion` when running
-    # pytest..
-    from packaging.version import LegacyVersion, Version
+from packaging.version import Version, parse
 
 from pants.backend.python.util_rules.pex_requirements import (
     LoadedLockfile,
@@ -34,7 +29,7 @@
 
 @dataclass(frozen=True, order=True)
 class PythonRequirementVersion:
-    _parsed: LegacyVersion | Version
+    _parsed: Version
 
     @classmethod
     def parse(cls, version: str) -> PythonRequirementVersion:


Reviews:
user: login: huonw
body: Looks reasonable other than the breaking change question. 

For background, is this upgrade motivated by something in particular or just a "keeping up" maintenance one?
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-01T06:11:19Z
user: login: tdyas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-01T13:30:50Z
user: login: huonw
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T01:30:14Z
user: login: huonw
body: Looks good, other than a bullet point in the release notes 👍 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T01:30:42Z
user: login: tdyas
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-02T05:35:14Z

Review comments:
diff_hunk: @@ -34,7 +29,7 @@
 
 @dataclass(frozen=True, order=True)
 class PythonRequirementVersion:
-    _parsed: LegacyVersion | Version
path: src/python/pants/backend/python/util_rules/lockfile_diff.py
user: login: huonw
body: I take it `LegacyVersion` is no longer supported as of packaging 22.0... is that possibly a breaking change for Pants users?
created_at: 2025-03-01T06:10:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,7 +29,7 @@
 
 @dataclass(frozen=True, order=True)
 class PythonRequirementVersion:
-    _parsed: LegacyVersion | Version
path: src/python/pants/backend/python/util_rules/lockfile_diff.py
user: login: tdyas
body: Can users even generate a lockfile with legacy versions? Given [PEP 440](https://peps.python.org/pep-0440/) has been around since 2013, I'm inclined to just wait for a user to complain about the lockfile diff not working and then  just have the user upgrade the offending dependency (or potentially asking the user to sponsor work to vendor `LegacyVersion` at that time).
created_at: 2025-03-01T13:30:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,7 +29,7 @@
 
 @dataclass(frozen=True, order=True)
 class PythonRequirementVersion:
-    _parsed: LegacyVersion | Version
path: src/python/pants/backend/python/util_rules/lockfile_diff.py
user: login: huonw
body: Sounds good 👍  although given there's a chance of behaviour change maybe we could have a quick note in the release notes to give people a starting point for answering "why did this change?!"
created_at: 2025-03-02T01:30:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -34,7 +29,7 @@
 
 @dataclass(frozen=True, order=True)
 class PythonRequirementVersion:
-    _parsed: LegacyVersion | Version
path: src/python/pants/backend/python/util_rules/lockfile_diff.py
user: login: tdyas
body: Done.
created_at: 2025-03-02T05:35:14Z
author_association: CONTRIBUTOR

PR comments:
user: login: tdyas
created_at: 2025-03-01T12:01:06Z
body: > For background, is this upgrade motivated by something in particular or just a "keeping up" maintenance one?

Because I want to [upgrade `mypy`](https://github.com/pantsbuild/pants/pull/21873), but our use of deprecated `pkg_resources` was causing problems there. And part of the solution is migrating from `pkg_resources` to `packaging` directly. So upgrade `packaging` as a first step.
author_association: CONTRIBUTOR
user: login: sureshjoshi
created_at: 2025-03-01T12:52:37Z
body: Adding Changelog so it's easier to see what changed: https://github.com/pypa/packaging/blob/main/CHANGELOG.rst
author_association: MEMBER