diff --git a/doc/nitpick-exceptions.txt b/doc/nitpick-exceptions.txt
index 0af3c739ade938184477a2ec5f052bc59b5eec42..fbcc656d720d86ee56b2f6d086f433f90c01e203 100644
--- a/doc/nitpick-exceptions.txt
+++ b/doc/nitpick-exceptions.txt
@@ -3,7 +3,6 @@
 # SPDX-License-Identifier: BSD-3-Clause
 
 py:class conda_build.config.Config
-py:class pkg_resources.Requirement
+py:class packaging.requirements.Requirement
 py:class os._Environ
 py:class _io.StringIO
-py:class packaging.requirements.Requirement
diff --git a/src/idiap_devtools/gitlab/release.py b/src/idiap_devtools/gitlab/release.py
index e14656a2d9134d85c93fb7c181a54560a1703a67..8a485db660e064d0ccb36ea478c9dc5c1077f06d 100644
--- a/src/idiap_devtools/gitlab/release.py
+++ b/src/idiap_devtools/gitlab/release.py
@@ -12,11 +12,11 @@ from distutils.version import StrictVersion
 
 import gitlab
 import gitlab.v4.objects
+import packaging.requirements
 import packaging.version
 import tomlkit
 
 from git import Repo
-from pkg_resources import Requirement
 
 from idiap_devtools.profile import Profile
 
@@ -95,7 +95,7 @@ def _update_readme(
 
 def _pin_versions_of_packages_list(
     packages_list: list[str],
-    dependencies_versions: list[Requirement],
+    dependencies_versions: list[packaging.requirements.Requirement],
 ) -> list[str]:
     """Add its version to each package according to a dictionary of versions.
 
@@ -127,15 +127,15 @@ def _pin_versions_of_packages_list(
     # Check that there is not the same dependency twice in the pins
     seen = set()
     for d in dependencies_versions:
-        if d.key in seen:
+        if d.name in seen:
             raise NotImplementedError(
                 "Pinning with more than one specification per dependency not"
                 "supported."
             )
-        seen.add(d.key)
+        seen.add(d.name)
 
     # Make it easier to retrieve the dependency pin for each package.
-    dependencies_dict = {d.key: d for d in dependencies_versions}
+    dependencies_dict = {d.name: d for d in dependencies_versions}
 
     results = []
 
@@ -144,31 +144,31 @@ def _pin_versions_of_packages_list(
         results.append(package)
 
         # Get the dependency package version specifier if already present.
-        pkg_req = Requirement.parse(package)
+        pkg_req = packaging.requirements.Requirement(package)
 
         if pkg_req.url is not None:
             logger.warning(
                 "Ignoring dependency '%s' as it is specified with a url (%s).",
-                pkg_req.key,
+                pkg_req.name,
                 pkg_req.url,
             )
 
         # Retrieve this dependency's constraint Requirement object
-        desired_pin = dependencies_dict.get(pkg_req.key)
+        desired_pin = dependencies_dict.get(pkg_req.name)
 
         if desired_pin is None:
             logger.warning(
                 "Dependency '%s' is not available in constraints. Skipping "
                 "pinning. Consider adding this package to your dev-profile "
                 "constraints file.",
-                pkg_req.key,
+                pkg_req.name,
             )
             continue
 
         # A Requirement is composed of:
-        #   key[extras]@ url ; marker
+        #   name[extras]@ url ; marker
         # Or
-        #   key[extras]specifier; marker
+        #   name[extras]specifier; marker
         # Where extras and marker are optional
 
         # The following handles those different fields
@@ -176,29 +176,26 @@ def _pin_versions_of_packages_list(
         if desired_pin.url is not None:
             logger.info(
                 "Pinning of %s will be done with a URL (%s).",
-                pkg_req.key,
+                pkg_req.name,
                 desired_pin.url,
             )
         else:
             # Build the 'specs' field
-            if len(desired_pin.specs) == 0:
+            if not desired_pin.specifier:
                 logger.warning(
                     "Dependency '%s' has no version specifier in constraints "
                     "'%s'. Skipping pinning.",
-                    pkg_req.key,
+                    pkg_req.name,
                     desired_pin,
                 )
                 continue
 
             # If version specifiers are already present in that dependency
-            if len(pkg_req.specs) > 0:
+            if pkg_req.specifier:
                 raise ValueError(
                     f"You cannot specify a version for the dependency {pkg_req}"
                 )
-            desired_specs = desired_pin.specs
-
-            # Set the version of that dependency to the pinned one.
-            specs_str = ",".join("".join(s) for s in desired_specs)
+            specs_str = str(desired_pin.specifier)
 
         # Build the 'marker' field
         if pkg_req.marker is not None:
@@ -225,7 +222,7 @@ def _pin_versions_of_packages_list(
         if desired_pin.url is not None:
             final_str = "".join(
                 (
-                    pkg_req.key,
+                    pkg_req.name,
                     extras_str,
                     "@ ",
                     desired_pin.url,
@@ -235,11 +232,13 @@ def _pin_versions_of_packages_list(
             )
         else:
             final_str = "".join(
-                (pkg_req.key, extras_str, specs_str, marker_str)
+                (pkg_req.name, extras_str, specs_str, marker_str)
             )
 
         # Replace the package specification with the pinned version
-        packages_list[pkg_id] = str(Requirement.parse(final_str))
+        packages_list[pkg_id] = str(
+            packaging.requirements.Requirement(final_str)
+        )
         logger.debug("Package pinned: %s", packages_list[pkg_id])
 
     return packages_list
diff --git a/src/idiap_devtools/profile.py b/src/idiap_devtools/profile.py
index b242241344b342f2453797c3c754ae230a78efdd..acc9fd828a028d235055d302e3793a79d77c2261 100644
--- a/src/idiap_devtools/profile.py
+++ b/src/idiap_devtools/profile.py
@@ -6,7 +6,7 @@ import io
 import pathlib
 import typing
 
-import pkg_resources
+import packaging.requirements
 import tomli
 import xdg
 import yaml
@@ -325,11 +325,13 @@ class Profile:
             for p, v in package_pins.items()
         }
 
-    def python_constraints(self) -> list[pkg_resources.Requirement] | None:
+    def python_constraints(
+        self,
+    ) -> list[packaging.requirements.Requirement] | None:
         """Return a list of Python requirements given the current profile."""
         content = self.get_file_contents(("python", "constraints"))
 
         if content is None:
             return None
 
-        return list(pkg_resources.parse_requirements(content))
+        return [packaging.requirements.Requirement(k) for k in content.split()]
diff --git a/src/idiap_devtools/scripts/fullenv.py b/src/idiap_devtools/scripts/fullenv.py
index a39bdf21d0fb7ec2f179606844e268025d5d3983..936647873f69cede039afb383f7b1d34dac7be30 100644
--- a/src/idiap_devtools/scripts/fullenv.py
+++ b/src/idiap_devtools/scripts/fullenv.py
@@ -123,8 +123,7 @@ def fullenv(
     python_packages = [
         k
         for k in python_packages
-        if python_to_conda.get(k.project_name, k.project_name)
-        not in conda_packages
+        if python_to_conda.get(k.name, k.name) not in conda_packages
     ]
 
     data: dict[str, typing.Any] = dict(channels=["conda-forge"])
diff --git a/tests/test_release.py b/tests/test_release.py
index 1b5099c3917e57cd486d055f11818d73df043faf..1d1f493d3816dceaadb81f3435fdc2662686767f 100644
--- a/tests/test_release.py
+++ b/tests/test_release.py
@@ -5,7 +5,7 @@
 import pytest
 
 from idiap_devtools.gitlab import release
-from pkg_resources import Requirement
+from packaging.requirements import Requirement
 
 
 def test_pinning_no_constraints():