Skip to content

Commit 79a41d1

Browse files
authored
PEP 735: apply community feedback, including reversion of [project] table changes (#3990)
1 parent 23530a8 commit 79a41d1

File tree

1 file changed

+97
-135
lines changed

1 file changed

+97
-135
lines changed

peps/pep-0735.rst

Lines changed: 97 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ which this PEP seeks to support:
5151

5252
* non-package projects, such as data science projects
5353

54+
Several motivating use cases are defined in detail in the :ref:`Use Cases Appendix <use_cases>`.
55+
5456
Limitations of ``requirements.txt`` files
5557
-----------------------------------------
5658

@@ -95,8 +97,11 @@ package specifiers which are published as part of a package's metadata, and
9597
which a user can request under that name, as in ``pip install 'foo[bar]'`` to
9698
install ``foo`` with the ``bar`` extra.
9799

98-
Because ``extras`` are package metadata, they are not usable when a project
99-
does not build a distribution (i.e., is not a package).
100+
Because ``extras`` are package metadata, they are not guaranteed to be
101+
statically defined and may require a build system to resolve.
102+
Furthermore, definition of a ``[project.optional-dependencies]`` indicates to
103+
many tools that a project is a package, and may drive tool behaviors such as
104+
validation of the ``[project]`` table.
100105

101106
For projects which are packages, ``extras`` are a common solution for defining
102107
development dependencies, but even under these circumstances they have
@@ -163,24 +168,6 @@ defined in greater detail in the :ref:`Use Cases Appendix <use_cases>`.
163168
be used as a location for locked dependency data)
164169
* Input data to an environment manager, such as tox, Nox, or Hatch
165170
* Configurable IDE discovery of test and linter requirements
166-
* Exposure of package dependencies for install, without the package itself
167-
168-
Support for Inclusion from ``project.dependencies``
169-
---------------------------------------------------
170-
171-
The ``project.dependencies`` and ``project.optional-dependencies`` tables are
172-
allowed to include Dependency Groups, requiring an update to the specification
173-
of these tables.
174-
175-
The drivers for such changes are that some usages are well solved by the
176-
addition of such support, and that failing to include support in the initial
177-
Dependency Group PEP, but adding such support later in a subsequent PEP,
178-
would make the support landscape significantly more difficult for tool
179-
maintainers.
180-
181-
Inclusion of a Dependency Group in ``project.dependencies`` or
182-
``project.optional-dependencies`` takes the form of a Dependency Group Include,
183-
defined in the specification section below.
184171

185172
Regarding Poetry and PDM Dependency Groups
186173
------------------------------------------
@@ -255,12 +242,7 @@ Strings in requirement lists must be valid
255242
`Dependency Specifiers <https://packaging.python.org/en/latest/specifications/dependency-specifiers/>`__,
256243
as defined in :pep:`508`.
257244

258-
Tables in requirement lists must be valid Dependency Object Specifiers,
259-
defined below.
260-
261-
The ``project`` table in ``pyproject.toml`` is modified such that
262-
``project.dependencies`` and the values of ``project.optional-dependencies``
263-
may contain Dependency Object Specifiers.
245+
Tables in requirement lists must be valid Dependency Object Specifiers.
264246

265247
Dependency Object Specifiers
266248
----------------------------
@@ -310,21 +292,6 @@ Includes, in which case those includes should be expanded as well. Dependency
310292
Group Includes MUST NOT include cycles, and tools SHOULD report an error if
311293
they detect a cycle.
312294

313-
``project`` Table Changes
314-
-------------------------
315-
316-
The ``[project]`` table, originally defined in :pep:`621` is extended in two ways.
317-
318-
``dependencies``
319-
320-
In addition to :pep:`508` strings, the array may contain Dependency Object
321-
Specifiers.
322-
323-
``optional-dependencies``
324-
325-
In addition to :pep:`508` strings, the array values in this table may contain
326-
Dependency Object Specifiers.
327-
328295
Example Dependency Groups Table
329296
-------------------------------
330297

@@ -404,11 +371,10 @@ Tools MAY choose to provide the same interfaces for installing Dependency
404371
Groups as they do for installing extras.
405372

406373
Note that this specification does not forbid having an extra whose name matches
407-
a Dependency Group. In such cases, tools must define their own semantics for
408-
precedence order or disambiguation.
374+
a Dependency Group.
409375

410376
Users are advised to avoid creating Dependency Groups whose names match extras.
411-
Tools SHOULD NOT treat such matching as an error.
377+
Tools MAY treat such matching as an error.
412378

413379
Validation and Compatibility
414380
----------------------------
@@ -482,7 +448,7 @@ The output is therefore valid ``requirements.txt`` data.
482448
483449
484450
def _resolve_dependency_group(
485-
dependency_groups: dict, group: str, past_groups: tuple[str] = ()
451+
dependency_groups: dict, group: str, past_groups: tuple[str, ...] = ()
486452
) -> list[str]:
487453
if group in past_groups:
488454
raise ValueError(f"Cyclic dependency group include: {group} -> {past_groups}")
@@ -542,16 +508,15 @@ At time of writing, the ``dependency-groups`` namespace within a
542508
reserved for use only by standards specified at packaging.python.org,
543509
there are no direct backwards compatibility concerns.
544510

545-
However, the introduction of the feature as a potential component of
546-
``project`` data has implications for a number of ecosystem tools.
511+
However, the introduction of the feature has implications for a
512+
number of ecosystem tools, especially those which attempt to support
513+
examination of data in ``setup.py`` and ``requirements.txt``.
547514

548515
Audit and Update Tools
549516
----------------------
550517

551518
A wide range of tools understand Python dependency data as expressed in
552-
``project.dependencies`` and ``project.optional-dependencies`` and may
553-
additionally support ``setup.cfg``, ``requirements.txt``, and even
554-
``setup.py``. (e.g., Dependabot, Tidelift, etc)
519+
``requirements.txt`` files. (e.g., Dependabot, Tidelift, etc)
555520

556521
Such tools inspect dependency data and, in some cases, offer tool-assisted or
557522
fully automated updates.
@@ -563,31 +528,6 @@ As a result, users of Dependency Groups would experience a degradation in their
563528
workflows and tool support at the time that they start using Dependency Groups.
564529
This is true of any new standard for where and how dependency data are encoded.
565530

566-
Repackaging
567-
-----------
568-
569-
Repackaging, and in particular tool-assisted repackaging such as Grayskull or
570-
PyInstaller, will need to contend with the change to package metadata
571-
definitions as well.
572-
573-
Because repackagers for alternate ecosystems such as conda and linux distros
574-
are often distinct persons vs the package publishers, this compatibility
575-
concern is more difficult to address than cases in which the package
576-
maintainers experience the impact. Package maintainers may be unaware of the
577-
impact of beginning to use Dependency Groups, and may unknowingly make changes
578-
which harm downstream repackaging workflows.
579-
580-
There are two primary ways in which this issue can be addressed:
581-
582-
* via education and "How to Teach This" -- users whose packages are repackaged
583-
should be made aware that using new standards may cause issues for downstream
584-
package consumers
585-
586-
* by driving more behavior through build-backends -- so long as dependency
587-
metadata are gathered via :pep:`517` interfaces, downstream repackagers can
588-
remain ignorant of which build system is being used and whether or not it
589-
supports Dependency Groups
590-
591531
Security Implications
592532
=====================
593533

@@ -632,22 +572,6 @@ defined dynamically. Requirements loaded from ``requirements.txt`` files and
632572
definitions of static lists prior to ``setup()`` invocation readily analogize
633573
with Dependency Groups.
634574

635-
Notes for Packages which are Repackaged
636-
---------------------------------------
637-
638-
A special note should be given to package maintainers whose packages are
639-
repackaged by linux distros, homebrew, conda, etc.
640-
641-
Use of Dependency Group Includes in core project metadata,
642-
``project.dependencies`` and ``project.optional-dependencies``, may break these
643-
consumers' uses of your package. Because they may be consuming and directly
644-
interact with the source for your repository, their toolchains may not support
645-
Dependency Groups at the same time that the package maintainers' tools are
646-
updated.
647-
648-
Ensure that repackaging consumers can contact you if there is an issue, and
649-
make sure to note transitions to use Dependency Groups in your changelogs.
650-
651575
Interfaces for Use of Dependency Groups
652576
---------------------------------------
653577

@@ -779,18 +703,92 @@ has impacts on high-level tools like IDEs and Dependabot, which cannot support
779703
deep integration with these Dependency Groups. (For example, at time of writing
780704
Dependabot will not flag dependencies which are pinned in ``tox.ini`` files.)
781705

706+
Deferred Ideas
707+
==============
708+
709+
Why not support Dependency Group Includes in ``[project.dependencies]`` or ``[project.optional-dependencies]``?
710+
---------------------------------------------------------------------------------------------------------------
711+
712+
Earlier drafts of this specification allowed Dependency Group Includes to be
713+
used in the ``[project]`` table.
714+
However, there were several issues raised during community feedback which led
715+
to its removal.
716+
717+
Only a small number of additional use cases would be addressed by the inclusion
718+
of Dependency Groups, and it increased the scope of the specification
719+
significantly. In particular, this inclusion would increase the number of parties
720+
impacted by the addition. Many readers of the ``[project]`` table, including build
721+
backends, SBOM generators, and dependency analyzers are implicated by a change to
722+
``[project]`` but may continue to operate as-is in the presence of a new (but
723+
unconnected) ``[dependency-groups]`` table.
724+
725+
Separately from the above concern, allowing inclusion of dependency groups from the
726+
``[project]`` table encourages package maintainers to move dependency metadata out
727+
of the current standard location.
728+
This complicates static ``pyproject.toml`` metadata and conflicts with the goal of
729+
:pep:`621` to store dependency metadata in a single location.
730+
731+
Finally, exclusion of ``[project]`` support from this PEP is not final. The
732+
use of includes from that table, or an inclusion syntax from
733+
``[dependency-groups]`` into ``[project]``, could be introduced by a future
734+
PEP and considered on its own merits.
735+
736+
Use Cases for Dependency Group Includes From ``[project]``
737+
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
738+
739+
Although deferred in this PEP, allowing includes from the ``[project]``
740+
table would address several use cases.
741+
742+
In particular, there are cases in which package developers would like to
743+
install only the dependencies of a package, without the package itself.
744+
745+
For example:
746+
747+
* Specify different environment variables or options when building dependencies
748+
vs when building the package itself
749+
750+
* Creating layered container images in which the dependencies are isolated from
751+
the package being installed
752+
753+
* Providing the dependencies to analysis environments (e.g., type checking)
754+
without having to build and install the package itself
755+
756+
For an example of the last case, consider the following sample
757+
``pyproject.toml``:
758+
759+
.. code-block:: toml
760+
761+
[project]
762+
dependencies = [{include = "runtime"}]
763+
[optional-dependencies]
764+
foo = [{include = "foo"}]
765+
[dependency-groups]
766+
runtime = ["a", "b"]
767+
foo = ["c", "d"]
768+
typing = ["mypy", {include = "runtime"}, {include = "foo"}]
769+
770+
In this case, a ``typing`` group can be defined, with all of the package's
771+
runtime dependencies, but without the package itself. This allows uses of the
772+
``typing`` Dependency Group to skip installation of the package -- not only is
773+
this more efficient, but it may reduce the requirements for testing systems.
774+
782775
Why not support Dependency Group Includes in ``[build-system.requires]``?
783776
-------------------------------------------------------------------------
784777

785-
Although it may be interesting to allow this in the future, incorporating the
786-
proposal into the build-system table reduces the ability of users to rely on
787-
this to bootstrap support. :pep:`517` frontends would be required to support
788-
Dependency Groups in order to achieve this, and the versions of these frontends
789-
are not easily controlled by packages.
778+
Given that we will not allow for ``[project]`` usage of Dependency Groups,
779+
``[build-system.requires]`` can be considered in comparison with
780+
``[project.dependencies]``.
781+
782+
There are fewer theoretical usages for build requirements specified in a group
783+
than package requirements. Additionally, the impact of such a change implicates
784+
:pep:`517` frontend, which would need to support Dependency Groups in order to
785+
prepare a build environment.
790786

791-
By only defining build backend support, it is possible for packages to start
792-
leveraging the new syntax and capabilities without being concerned about
793-
controlling the environment in which the package is built and installed.
787+
Compared with changes to ``[project.dependencies]`` and
788+
``[project.optional-dependencies]``, changing the behaviors of
789+
``[build-system.requires]`` is higher impact and has fewer potential uses.
790+
Therefore, given that this PEP declines to make changes to the ``[project]``
791+
table, changing ``[build-system]`` is also deferred.
794792

795793
.. _prior_art:
796794

@@ -1411,42 +1409,6 @@ for various purposes.
14111409
This declaration allows the project author's knowledge of the appropriate tools
14121410
for the project to be shared with all editors of that project.
14131411

1414-
Exposure of package dependencies without the package itself
1415-
-----------------------------------------------------------
1416-
1417-
There are a variety of use-cases in which package developers would like to
1418-
install only the dependencies of a package, without the package itself.
1419-
1420-
For example:
1421-
1422-
* Specify different environment variables or options when building dependencies
1423-
vs when building the package itself
1424-
1425-
* Creating layered container images in which the dependencies are isolated from
1426-
the package being installed
1427-
1428-
* Providing the dependencies to analysis environments (e.g., type checking)
1429-
without having to build and install the package itself
1430-
1431-
For an example of the last case, consider the following sample
1432-
``pyproject.toml``:
1433-
1434-
.. code-block:: toml
1435-
1436-
[project]
1437-
dependencies = [{include = "runtime"}]
1438-
[optional-dependencies]
1439-
foo = [{include = "foo"}]
1440-
[dependency-groups]
1441-
runtime = ["a", "b"]
1442-
foo = ["c", "d"]
1443-
typing = ["mypy", {include = "runtime"}, {include = "foo"}]
1444-
1445-
In this case, a ``typing`` group can be defined, with all of the package's
1446-
runtime dependencies, but without the package itself. This allows uses of the
1447-
``typing`` Dependency Group to skip installation of the package -- not only is
1448-
this more efficient, but it may reduce the requirements for testing systems.
1449-
14501412
Copyright
14511413
=========
14521414

0 commit comments

Comments
 (0)