From 7bfbf2b7719aab953ca883ddf9d70c1c1cd340d8 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Fri, 2 May 2025 14:10:53 +0100 Subject: [PATCH 01/19] Started making changes in relation to accepting package[] as meaning no default extras --- peps/pep-0771.rst | 196 ++++++++++++---------------------------------- 1 file changed, 52 insertions(+), 144 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 5755afc377c..472721d716d 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -213,9 +213,10 @@ tree:: then the default extra should be installed because ``package`` appears at least once with no extras specified. -Note that ``package[]`` would continue to be equivalent to ``package`` and would -not be provided as a way to install without default extras (see the `Rejected -Ideas`_ section for the rationale). +An empty set of extras, such as ``package[]`` should be interpreted as meaning +that the package should be installed *without* any default extras (unless +``package`` appears elsewhere in the dependency tree as mentioned above), so +would provide a universal way of obtaining a minimal installation of a package. We also note that some tools such as `pip`_ currently ignore unrecognized extras, and emit a warning to the user to indicate that the extra has not been @@ -228,30 +229,9 @@ recognized, e.g: ... For tools that behave like this (rather than raising an error), if an extra is -recognized as invalid in a dependency specification, it should be ignored and -treated as if the user has not passed an explicit extra. If none of the provided -extras are valid, default extras should be installed. - -Installing without default extras ---------------------------------- - -In some cases, package maintainers may want to facilitate installing packages -without any default extras. In this case, as will be shown in more detail in -`Examples`_, the best approach is to define an extra which could be -called e.g. ``minimal`` or ``nodefault`` (the naming would be up to the package -maintainer) which would be an empty set of dependencies. If this extra is -specified, no default extras will be included, so that e.g. ``package[minimal]`` -would include only required dependencies and no extras. Note that this requires -no additional specification and is a natural consequence of the rule described -in `Overriding default extras`_. - -There are however valid use cases where package maintainers may not want to -provide this. For example, in the case of the multiple possible frontends or -backends, it may be that the package would not be functional without any of the -options. To take a specific example, a package may need either PyQt or PySide to -be installed but will not work if none are provided, so a package maintainer may -therefore not want to provide an option to install the package without any -extras. +recognized as invalid in a dependency specification, it should be ignored, and +if all specified extras are invalid, then this should be considered equivalent +to ``package[]`` (rather than ``package``) and not install any default extras. Examples -------- @@ -263,9 +243,9 @@ above. Recommended dependencies and minimal installations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -First, we consider the case of packages that want recommended -but not strictly required dependencies installed by default, while also -providing a way to only install the required dependencies. +First, we consider the case of packages that want recommended but not strictly +required dependencies installed by default, while also providing a way to only +install the required dependencies. In order to do this, a package maintainer would define an extra called ``recommended`` containing the recommended but not required dependencies, and @@ -284,34 +264,15 @@ would choose to have this be included as a default extra: "package2" ] -In this specific case, a package maintainer may want to allow users to also -install the package without the recommended dependencies, in which case they -could define an empty extra: - -.. code-block:: toml - - [project.optional-dependencies] - minimal = [] - recommended = [ - "package1", - "package2" - ] - -This would then allow users to install ``package[minimal]`` which, since -there would be an extra explicitly specified, would mean the default extra -does not get installed, and since the ``minimal`` extra is empty, no -additional dependencies would be installed. - -Maintainers would have the choice as to whether to offer the capability to do a -minimal installation or not - in some cases, such as highlighted in the next -section, this might not be desirable. +If this package was called ``package``, users installing ``package`` would +then get the equivalent of ``package[recommended]``. Users could alternatively +install ``package[]`` which would install the package without the default extras. To take a one of the concrete examples of package from the `Motivation`_ section, the `astropy`_ package defines a ``recommended`` extra that users are currently instructed to install in the default installation instructions. With this PEP, the ``recommended`` extra could be declared as being a default -extra, and a new ``minimal`` extra could be provided for users wishing to -retain the ability to install only the strictly required dependencies: +extra: .. code-block:: toml @@ -321,7 +282,6 @@ retain the ability to install only the strictly required dependencies: ] [project.optional-dependencies] - minimal = [] recommended = [ "scipy", "..." @@ -333,13 +293,13 @@ meaning that installing: $ pip install astropy -would then also install optional but important optional dependencies such as `scipy -`_. Advanced users who want a minimal -install could then use: +would then also install optional but important optional dependencies such as +`scipy `_. Advanced users who want a minimal install +could then use: .. code-block:: console - $ pip install astropy[minimal] + $ pip install astropy[] Packages requiring at least one backend or frontend @@ -372,10 +332,6 @@ for each backend or frontend, and provide a default, e.g.: "package3" ] -Unlike the previous example however, maintainers would not necessarily provide a -way to do an installation without any extras since it might leave the package in -an unusable state. - If packages can support e.g. multiple backends at the same time, and some of the backends should always be installed, then the dependencies for these must be given as required dependencies rather than using the default extras mechanism. @@ -425,16 +381,16 @@ explicitly specify a frontend, e.g.: $ pip install napari[pyside6] -Supporting minimal installations while not always removing default extras -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Supporting extras that should not remove default extras +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -An additional case we consider here is where a package maintainer wants to support -minimal installations without any extras, but also wants to support having users -specify additional extras without removing the default one. Essentially, they -would want: +An additional case we consider here is where a package maintainer wants to +support the ability for users to opt-in to non-default extras, without removing +default extras. Essentially, they might want: -* ``package[minimal]`` to give an installation without any extras +* ``package[]`` to give an installation without any extras * ``package`` to install recommended dependencies (in a ``recommended`` extras) +* ``package[alternative]`` to not install default extras, but to install an alternative set of optional dependencies (in an ``alternative`` extras) * ``package[additional]`` to install both recommended and additional dependencies (in an ``additional`` extras) This could be achieved with e.g: @@ -447,14 +403,16 @@ This could be achieved with e.g: ] [project.optional-dependencies] - minimal = [] recommended = [ "package1", "package2" ] + alternative = [ + "package3" + ] additional = [ "package[recommended]", - "package3" + "package4" ] The ability for a package to reference itself in the extras is supported by @@ -477,7 +435,6 @@ configuration would solve this case: ] [project.optional-dependencies] - minimal = [] recommended = [ "scipy", "..." @@ -540,10 +497,10 @@ dependencies to the dependency tree, and specifying some extras can result in fewer dependencies being installed. A specific example of change in behavior can be seen with `pip`_: consider a -package ``package`` which has a required dependency of ``numpy``, a (default) -extra called ``recommended`` which includes ``scipy``, and a ``minimal`` extra -which does not contain any dependencies. If a user installs ``package[minimal]``, -only ``package`` and ``numpy`` will be installed. If a user then does: +package ``package`` which has a required dependency of ``numpy``, and a default +extra called ``recommended`` which includes ``scipy``. If a user installs +``package[]``, only ``package`` and ``numpy`` will be installed. If a user then +does: .. code-block:: console @@ -630,24 +587,14 @@ following recommendations would apply: fraction of the user community) will start getting the recommended dependencies by default. -* Adding a new extra, whether it be ``minimal`` or another new extra that is to - be the default, comes with the same caveats that it does prior to this PEP, which - is that users will only be able to use this extra for releases that define - this extra. This might seem obvious, but consider a package that has a version - 1.0 prior to using default extras. Suppose that package now defines - ``minimal`` in 2.0, then downstream users and packages that want to depend on - a minimal version of the package cannot declare the following dependency:: - - package[minimal]>=1.0 - - because ``package[minimal]==1.0`` does not exist (in practice, pip ignores - unknown extras, so it might be possible to do this, but there is no guarantee - that other tools won't error on an unrecognized extra). - - The easiest solution to this problem is for package authors to define a no-op - ``minimal`` extra as soon as possible, even if only planning to adopt default - extras further down the road, as it will allow ``package[minimal]`` to work - for versions prior to when defaults were adopted. +* Since prior to this PEP, ``package[]`` was equivalent to ``package``, + authors will be able to document ``package[]`` as a backward-compatible + universal way of getting a minimal installation. For packages that define + default extras, installing ``package[]`` will always give a minimal + installation even with older versions of packaging tools such as `pip`_, and + releases of this package that pre-date the introduction of default extras for + a specific package will also be installable with ``package[]`` (although in + these cases this will be equivalent to ``package``). Avoiding the addition of many default dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -664,10 +611,10 @@ Inheriting from default extras If package authors choose to make an extra be installed by default, it is important that they are aware that if users explicitly specify another extra, the default may -not be installed, unless they use the approach described in `Supporting minimal -installations while not always removing default extras`_. +not be installed, unless they use the approach described in `Supporting extras +that should not remove default extras`_. -There are cases, such as the interchangeable backends, or the ``minimal`` extras, +There are cases, such as the interchangeable backends, where ignoring the default if an extra is explicitly specified is the right thing to do. However, for other cases, such as using default extras to include recommended dependencies while still providing a way to do minimal installs, it @@ -708,26 +655,23 @@ consider the following dependency tree:: └── package2 └── package1 -If ``package1`` has a default extra named ``recommended`` and a ``minimal`` -extra which is empty, then: +If ``package1`` has a default extra named ``recommended`` then: .. code-block:: console - $ pip install package1[minimal] + $ pip install package1[] will still result in the ``recommended`` extra being installed if ``package2`` -continues to depend on ``package1`` (with no extras specified). If the dependency -tree was updated to instead be:: +continues to depend on ``package1`` (with no extras specified). This could be +solved by changing the dependency tree to instead be:: package1 └── package2 - └── package1[minimal] - -Then ``package1`` would no longer be installable with tools that do not yet -implement this PEP (if those tools would fail on unrecognized extras). Authors -therefore need to carefully consider a migration plan, coordinating with the -authors of ``package2``. + └── package1[] +assuming that ``package2`` indeed does not depend on any features provided by +the extra dependencies of ``package1``. Authors therefore need to carefully +consider a migration plan, coordinating with the authors of ``package2``. Packaging repository maintainers -------------------------------- @@ -898,42 +842,6 @@ rely on default extras at any point. Nevertheless, this PEP does not disallow this approach and it is up to the maintainers of different packaging tools to decide if they want to support this kind of option. -``package[]`` disables default extras -------------------------------------- - -Another way to specify not to install any extras, including default extras, would -be to use ``package[]``. However, this would break the current assumption in packaging tools that -``package[]`` is equivalent to ``package``, and may also result -in developers overusing ``[]`` by default even when it is not needed. As -highlighted in `How to teach this`_, there may also be cases where package -maintainers do not actually want to support an installation without any extras, -for example in cases where at least one backend or frontend must be installed. - -Open issues -=========== - -Should ``package[]`` disable default extras? --------------------------------------------- - -Currently, the PEP as written above does not allow ``package[]`` to be -equivalent to installing the package with no extras, but there would be some -benefits to allowing this: - -* It would avoid different packages using different names for a 'no default' - extras (e.g. ``minimal``, ``no-default``, ``no-defaults``) and reduce the - burden for people who don’t want to have to scan through source code or - documentation to figure out whether there is the equivalent of a ``minimal`` - extra. - -* It would allow people who want to use existing packages as-is and future - versions of those packages with no default extras to use ``package[]`` because - that syntax works right now, so it would provide a consistent way over time to - get a minimal install. - -On the other hand, it is not clear at this point whether any tools are currently -relying on ``package[]`` being identical to ``package`` in a way that would -break compatibility if this was done, so this needs to be investigated. - Copyright ========= From 02840eb94e0b4a12c44338accc615f73fdc40b82 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 11:59:46 +0100 Subject: [PATCH 02/19] Added section on approach of splitting packages --- peps/pep-0771.rst | 167 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 472721d716d..f1f9371464e 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -731,6 +731,173 @@ functional enough to allow for interested maintainers to try these out. Rejected Ideas ============== +Using a meta-package for recommended installations +-------------------------------------------------- + +Using existing packaging tools and infrastructure, package maintainers who want +to provide a minimal installation for some users and a default non-minimal +installation for regular users (e.g. with recommended dependencies or a default +backend) can technically already achieve this if they are willing to distribute +two packages instead of one -- for example ``package-core`` which would be the main package +with minimal dependencies, and ``package`` which would be a metapackage that +would depend on ``package-core`` with optional dependencies enabled. + +Taking once again a concrete example from the `Motivation`_ +section, the `astropy`_ package defines a ``recommended`` extra that users are +currently instructed to install in the default installation instructions. +In principle, one could rename the existing ``astropy`` package to e.g. ``astropy-core`` +and then create a new ``astropy`` package which would be a metapackage that would +contain the following dependencies section: + +.. code-block:: toml + + dependencies = [ + "astropy-core[recommended]" + ] + +Since users may want to pin or place version constraints on the ``astropy`` +meta-package (e.g. ``astropy>5.0``), the metapackage would need to follow +the same versions as the core package, and would need to use strict pinning +in the dependency section, e.g.: + +.. code-block:: toml + + version = "7.1.0" + dependencies = [ + "astropy-core[recommended]==7.1.0" + ] + +This idea may seem appealing because it is technically already feasible. However, in +practice, many projects have opted not to do this, for a number of reasons, which +we now take a look at. + +Mismatch between package and module name +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In terms of naming, there are two main options for a package that wants to use the metapackage +approach: + +* The first option is for the existing package to be kept as-is, which means + that ``package`` would provide the minimal installation, and to then create a + new metapackage with a different name, such as ``package-all``. However, this + suffers from one of the problems that motivated this PEP in the first place - + users are often not aware that they can do e.g. ``package[recommended]``, so + in the same way, they might not realise that ``package-all`` exists. This once + again places the burden on the average user to discover this, rather then + shifting some of the burden to more advanced users. + +* The second option is for the existing package to be renamed to e.g. ``package-core``, and + for the new meta-package to be called ``package``. This is a better option + than the first one, but is not ideal, as it then introduces a non-intuitive + mismatch between the package name and module name, in that ``package-core`` provides + the ``package`` module, and ``package`` does not provide any module. An example of why + this would lead to confusion is that an average user might think that uninstalling + the ``package`` module would be done with e.g.: + + .. code-block:: shell + + $ pip uninstall package + + but this would not be the case (the ``package`` module would still work), and + it may not be obvious to this user that the ``package-core`` package even + exists. + +Multiple repositories or monorepos +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This approach requires either maintaining two repositories instead of one, or +switching to using a monorepo which would contain both packages. Neither option +is ideal: + +* Splitting into two repositories places a long-term additional burden on + maintainers, who have to make sure that these stay in sync (in terms of + version but also other aspects such as extras, as will be discussed in + `Synchronizing metadata`_). In addition, the naming issue mentioned in + `Mismatch between package and module name`_ has additional complications here + – either the names of the repositories match the packages, in which case any + user who has a checkout of the previous ``package`` repository will need to + update their remote URLs or any git clone URLs to point to the + ``package-core`` repository. The alternative is to preserve the ``package`` + repository to contain the ``package-core`` package, and have a different name + for the meta-package, but this could lead to confusion. + +* Switching to a monorepo may be a significant change for some projects, + and it is not uncommon for tools to assume by default that a single repository + corresponds to a single package - while these can often be configured to then + work with a monorepo, it is an additional burden on the maintainers. In + addition, if the main package is moved to a sub-directory in the monorepo, any + user that is e.g. pip installing the package from the repository URL will need + to adjust this to install from a sub-directory (adding ``subdirectory=`` to + the repo URL), and any existing workflows that clone the repository and assume + the previous layout would break. + +Depending on the minimal package +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Packages that need to depend on package versions that are older than the first +version where the split was done will not easily be able to depend on the +minimal package. Whereas with the main proposal in this PEP, downstream users +will be able to depend on e.g. ``package[]>version`` where ``version`` pre-dates +the introduction of default extras, with the splitting approach it will not be +possible for downstream users to depend on e.g. ``package-core>version``, since +``package-core`` did not previously exist. + +A possible solution to this is for developers to release no-op metadata packages +for all old versions of a package, but this is a significant additional burden +on the maintainers. + +Uninstallation +^^^^^^^^^^^^^^ + +As alluded to when referring to naming issues in `Mismatch between package and +module name`_, uninstalling packages will no longer work the way users expect. A +user doing: + +.. code-block:: shell + + $ pip uninstall package + +will still be left with ``package-core``, but may not realise it. This is +not just confusing, but is in effect a breaking change that may impact a number +of existing workflows. + +Package distributions +^^^^^^^^^^^^^^^^^^^^^ + +Having two packages instead of one would increase the long-term maintenance cost +of package distributions simply by virtue of the fact that two packages would +have to be released instead of one. To take the example of conda-forge, two +repositories would now be required, and the version pinning would need to be +updated manually every time. The metapackage could only be built once the core +package had been built and published, which would lengthen the release process. + +Synchronizing metadata +^^^^^^^^^^^^^^^^^^^^^^ + +The main metadata that would be important to keep synchronized between the main +package and the metapackage is the version. Anytime a new release of the core +package is done, the metapackage would need to have its version updated as well +as the version pinning for the core package in the dependencies. + +In addition, all extras defined in the core package would need to be redefined +and kept in sync in the metapackage. For example, if ``package`` defines a +``additional`` extra, users should still be able to install +``package[additional]``, but users installing the ``package-core`` package should +also have the option of doing ``package-core[additional]``. + +Other metadata that would need to be kept in sync includes for example author +information and project URLs. + +Summary +^^^^^^^ + +Overall, this solution would imply a significantly higher maintenance burden, +not just in terms of initial set-up and transition (which could already be +prohibitive for large established projects), but also in terms of long-term +maintenance. This also has the potential for breaking user workflows (in +particular around the issue of repositories, and e.g. uninstallation), so for +this reason we do not consider it a compelling alternative to the present PEP. + Syntax for deselecting extras ----------------------------- From 3cbe02b291d6eaaaff073dd177dbb9307620a9cd Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 13:23:49 +0100 Subject: [PATCH 03/19] Added section on packages with multiple frontends/backends --- peps/pep-0771.rst | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index f1f9371464e..489f066f849 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -457,6 +457,56 @@ would then get the same as: $ pip install astropy[recommended, jupyter] +Packages with multiple kinds of defaults +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In some cases, it may be that packages need multiple kinds of defaults. As an example, +in `Packages requiring at least one backend or frontend`_, we considered the case of packages +that have *either* backends or frontends, but in some cases, packages may have to support +backends *and* frontends, and want to specify a default frontend and a default backend. + +Ideally, one may want the following behavior: + +.. code-block:: console + + $ pip install package # installs default backend and frontend + $ pip install package[] # installs no backends or frontends + $ pip install package[backend1] # installs backend1 and default frontend + $ pip install package[frontend2] # installs frontend2 and default backend + $ pip install package[backend1, frontend2] # installs backend1 and frontend2 + +However, this PEP chooses not to provide a mechanism for having the fact that +``backend1`` is specified disabling the default backend but keep the default +frontend, since this adds complexity. + +Maintainers should instead for now document that if a backend or frontend is +explicitly specified, both backend and frontend need to be specified. +Discoverability for users who want to do this should not be an issue however since users +need to read the documentation in any case to find out what backends or frontends are +available, so they can be shown at the same time how do properly use the extras for +backends and frontends. + +One option to increase user friendliness is that maintainers can create extras +called for example ``defaultbackend`` and ``defaultfrontend`` which do install +the default backend and frontend. They can then recommend that users do: + +.. code-block:: console + + $ pip install package # installs default backend and frontend + $ pip install package[] # installs no backends or frontends + $ pip install package[backend1, defaultfrontend] # installs backend1 and default frontend + $ pip install package[defaultbackend, frontend2] # installs frontend2 and default backend + $ pip install package[backend1, frontend2] # installs backend1 and frontend2 + +This would allow (if desired) users to then get whatever the recommended backend +is, even if that default changes in time. + +If there was a desire to implement a better solution in future, we believe this +PEP does not preclude this. For example, one could imagine in future adding the +ability for an extra to specify *which* default extras it disables rather than +disabling all default extras, but the default could still be for explicitly +specified extras to disable all default extras, which would be consistent with +the present PEP. Backward Compatibility ====================== From 45729b754562e0c3c401031dbeaaa57d47606092 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 13:31:01 +0100 Subject: [PATCH 04/19] Add reference to PEP 751 --- peps/pep-0771.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 489f066f849..c0e12640a25 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -574,6 +574,13 @@ resolving the dependency tree, but the point here is to illustrate that there may be changes in behavior in packaging tools due to the change in the assumption about what impact an extra can have. +It is worth noting that the recently-accepted :pep:`751` defines a new file +format which is intended to replace alternatives such as the ``pip freeze`` +output and other tools in future. The new file format is designed so that the +packages in the file are installed *without* resolving dependencies, which means +that it will be fully compatible with default extras as specified in this PEP, +and will avoid the issue with ``pip freeze``/``pip install -r`` mentioned above. + Security Implications ===================== From 1f9b40c37f17ab2417bb80cdc797a4b023874f78 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 13:58:06 +0100 Subject: [PATCH 05/19] Added section on documenting extras --- peps/pep-0771.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index c0e12640a25..4c40d3b3949 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -730,6 +730,23 @@ assuming that ``package2`` indeed does not depend on any features provided by the extra dependencies of ``package1``. Authors therefore need to carefully consider a migration plan, coordinating with the authors of ``package2``. +Documenting packages with default extras +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Regardless of how default extras are used, package authors should aim to ensure +that the documentation for their package makes it clear how extras are to be +used. 'Best practices' documentation should mention: + +* that installing ``package`` will be equivalent to ``package[]`` +* that installing ``package[]`` will include only minimal/required dependencies, + but that this will not guarantee that optional dependencies do not get installed + if ``package`` appears anywhere else in the dependency tree +* what other optional extras are available, and whether or not they disable the + default extras (since this can be controlled as described in `Supporting + extras that should not remove default extras`_) +* any instructions specific to packages that might have e.g. default backends + *and* frontends (as described in `Packages with multiple kinds of defaults`_) + Packaging repository maintainers -------------------------------- From 7d17a3cf11766a3a91bac8400cd42f2e067dbea1 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 14:03:03 +0100 Subject: [PATCH 06/19] Minor wording in --no-default-extras section --- peps/pep-0771.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 4c40d3b3949..c90756fbf25 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -1075,13 +1075,18 @@ The advantage of this approach is that tools supporting default extras could also support unselecting them. This approach would be similar to the ``--no-install-recommends`` option for the ``apt`` tool. -However, this solution is not ideal because it would not allow packages to +However, this solution is not ideal on its own because it would not allow packages to specify themselves that they do not need some of the default extras of a dependency. It would also carry risks for users who might disable all default extras in a big dependency tree, potentially breaking packages in the tree that -rely on default extras at any point. Nevertheless, this PEP does not disallow -this approach and it is up to the maintainers of different packaging tools to -decide if they want to support this kind of option. +rely on default extras at any point. + +Nevertheless, this PEP does not disallow this approach and it is up to the +maintainers of different packaging tools to decide if they want to support this +kind of option. It is a flag that could at the very least be useful for package +maintainers who want to identify places in dependency trees where default extras +are being relied on. However, if it is supported, it should be made clear that +using this flag does not guarantee a functional environment. Copyright ========= From dd2f519a9ca8a41601f9e956f598e02210b4d3ee Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 14:13:36 +0100 Subject: [PATCH 07/19] Updated examples --- peps/pep-0771.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index c90756fbf25..255aad597ba 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -51,8 +51,8 @@ Examples of packages that demonstrate this pattern by encouraging users to include extra dependencies by default include: * `astropy `_: ``astropy[recommended]`` +* `sunpy `_: ``sunpy[all]`` * `fastapi `_: ``fastapi[standard]`` -* `tensorflow `_: ``tensorflow[and-cuda]`` Packages supporting multiple backends or frontends -------------------------------------------------- @@ -67,8 +67,8 @@ is. Concrete examples of such frontends or backends include: `_, `PySide2 `_, or `PySide6 `_ -* BLAS/LAPACK, which have different possible implementations (e.g. OpenBLAS, and MKL) -* FFT libraries, which also have different implementations (e.g. ``scipy.fft`` and pyFFTW) +* Backend databases, such as `MySQL `_, `PostgreSQL + `_, `SQLite `_ With current packaging standards, maintainers have to either require one of the backends or frontends, or require users From 6ebf46932fe14defd8b2ddd1bba8b74f73f71896 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 14:21:37 +0100 Subject: [PATCH 08/19] Added paragraph about bloating and pytest --- peps/pep-0771.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 255aad597ba..63000451cf8 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -663,6 +663,18 @@ installations and complicating dependency trees. Using default extras does not mean that all extras need to be defaults, and there is still scope for users to explicitly opt in to non-default extras. +In essence, default extras should be considered just as 'weighty' as a required +dependency. In some cases, if a package is widely used by many others, if it +adds a default extra, then unless all downstream packages update their +dependencies to specifically request a minimal installation, the defaults will +often end up getting installed. A concrete example of this is that the `pytest +`_ package has almost 1500 plugins at the time of +writing, all of which depend on pytest. If pytest was to start using a default +extra, it would need to consider this very carefully, as if the plugins are not +updated, installing any plugin will result in the default extra being +installed. This is not to say that it should not use default extras, but just +that the decision should be considered and planned carefully. + Inheriting from default extras ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 763f81b9ab865e610f22898b88d15bb653c64573 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 14:22:14 +0100 Subject: [PATCH 09/19] Emphasis --- peps/pep-0771.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 63000451cf8..b6da10e247a 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -231,7 +231,7 @@ recognized, e.g: For tools that behave like this (rather than raising an error), if an extra is recognized as invalid in a dependency specification, it should be ignored, and if all specified extras are invalid, then this should be considered equivalent -to ``package[]`` (rather than ``package``) and not install any default extras. +to ``package[]`` (rather than ``package``) and *not* install any default extras. Examples -------- From 573103839b40eab0547d27579f7b8b5abc2d07bb Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 14:28:06 +0100 Subject: [PATCH 10/19] Added paragraph about tools being allowed to modify default extras behavior --- peps/pep-0771.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index b6da10e247a..339965d4517 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -233,6 +233,14 @@ recognized as invalid in a dependency specification, it should be ignored, and if all specified extras are invalid, then this should be considered equivalent to ``package[]`` (rather than ``package``) and *not* install any default extras. +Finally, we note (as also discussed in `Relying on tooling to deselect +any default extras`_) that package installers are allowed to implement their +own options to control the above behavior, for example implementing an option +that disables default extras for some or all packages regardless of where these +packages appear in the dependency tree -- although if such options are +implemented, they should be opt-in, and users should experience the above +behavior as default. + Examples -------- From b8f1509f2f8915d8f58ba546e330096a4e33bdf4 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Mon, 12 May 2025 14:42:48 +0100 Subject: [PATCH 11/19] Grammar and spelling --- peps/pep-0771.rst | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 339965d4517..d2115c960b3 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -25,7 +25,7 @@ Motivation Various use cases for default extras and possible solutions in this PEP were discussed extensively on `this DPO thread `__. -These fall into two broad cases that that provide the +These fall into two broad cases that provide the motivation for the present PEP. Recommended but not required dependencies @@ -35,7 +35,7 @@ Package maintainers often use extras to declare optional dependencies that extend the functionality or performance of a package. In some cases, it can be difficult to determine which dependencies should be required and which should be categorized as extras. A balance must be struck between the needs of typical -users (who may prefer most features to be available 'by default') and users who +users, who may prefer most features to be available by default, and users who want minimal installations without large, optional dependencies. One solution with existing Python packaging infrastructure is for package maintainers to define an extra called, for example, ``recommended``, which @@ -71,15 +71,15 @@ is. Concrete examples of such frontends or backends include: `_, `SQLite `_ With current packaging standards, maintainers have to either -require one of the backends or frontends, or require users -to always specify extras, e.g. ``package[backend]`` and therefore risk users +require one of the backends or frontends or require users +to always specify extras, e.g., ``package[backend]``, and therefore risk users having an unusable installation if they only install ``package``. Having a way to specify one or more default backend or frontend and providing a way to override these defaults would provide a much better experience for users, and the approach described in this PEP will allow this. Note that this PEP does not aim to address the issue of disallowing conflicting -or incompatible extras - for example if a package requires exactly one frontend +or incompatible extras, for example if a package requires exactly one frontend or backend package. There is currently no mechanism in Python packaging infrastructure to disallow conflicting or incompatible extras to be installed, and this PEP does not change that. @@ -94,13 +94,13 @@ recommend a default extra to install a backend or frontend include: * `glueviz `_: ``glueviz[qt]`` In all three cases, installing the package without any extras results in a -broken installation (and this is a commonly reported issue for some of these -packages). +broken installation, and this is a commonly reported issue for some of these +packages. Rationale ========= -A number of possible solutions have been extensively and vigorously discussed by +A number of possible solutions have been extensively discussed by the community for several years, including in `this DPO thread `__ as well as in numerous issues and pull requests. The solution that is @@ -110,7 +110,7 @@ presented below: * is flexible enough to accommodate both of the major use cases described in `Motivation`_ * re-uses the syntax from :pep:`508` -It is the only solution out of all those discussed that meets all three criteria. +It is the only solution, out of all those discussed, that meets all three criteria. Specification ============= @@ -121,7 +121,7 @@ Specification A new multiple-use metadata field, ``Default-Extra``, will be added to the `core package metadata `_. For this field, each entry must be a string specifying an extra that will be -automatically included when the package is installed without any extras specified explicitly. +automatically included when the package is installed without any extras being specified explicitly. Only entries already specified in a `Provides-Extra `_ @@ -174,7 +174,6 @@ and: "backend3" ] - Overriding default extras ------------------------- @@ -309,7 +308,6 @@ could then use: $ pip install astropy[] - Packages requiring at least one backend or frontend ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -483,8 +481,8 @@ Ideally, one may want the following behavior: $ pip install package[frontend2] # installs frontend2 and default backend $ pip install package[backend1, frontend2] # installs backend1 and frontend2 -However, this PEP chooses not to provide a mechanism for having the fact that -``backend1`` is specified disabling the default backend but keep the default +However, this PEP chooses not to provide a mechanism for making it so that e.g., if +``backend1`` is specified, this disabling the default backend but keeps the default frontend, since this adds complexity. Maintainers should instead for now document that if a backend or frontend is @@ -509,8 +507,8 @@ the default backend and frontend. They can then recommend that users do: This would allow (if desired) users to then get whatever the recommended backend is, even if that default changes in time. -If there was a desire to implement a better solution in future, we believe this -PEP does not preclude this. For example, one could imagine in future adding the +If there is a desire to implement a better solution in future, we believe this +PEP should not preclude this. For example, one could imagine in future adding the ability for an extra to specify *which* default extras it disables rather than disabling all default extras, but the default could still be for explicitly specified extras to disable all default extras, which would be consistent with @@ -648,7 +646,7 @@ following recommendations would apply: the extra explicitly as long as possible (until it is clear that most/all users are using package installers that implement this PEP). There is no downside to keeping the extra be explicitly mentioned, but this will ensure that users with - modern tooling who do not read documentation (which may be a non-negligeable + modern tooling who do not read documentation (which may be a non-negligible fraction of the user community) will start getting the recommended dependencies by default. @@ -816,8 +814,6 @@ In addition, `this branch `_ package. - - The implementations above are proofs-of-concept at this time and the existing changes have not yet been reviewed by the relevant maintainers. Nevertheless, they are functional enough to allow for interested maintainers to try these out. @@ -1051,7 +1047,6 @@ a ``setup.py`` file can do:: extras_require={'': ['package_a']}, ) - which is valid and equivalent to having ``package_a`` being defined in ``install_requires``, so changing the meaning of the empty string would break compatibility. From 57f05c9a9270debf7d7e2a2f5027fb3e20f0ce56 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Tue, 20 May 2025 14:09:37 +0100 Subject: [PATCH 12/19] Minor wording for package distributions --- peps/pep-0771.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index d2115c960b3..2f1f93de781 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -859,7 +859,8 @@ in the dependency section, e.g.: This idea may seem appealing because it is technically already feasible. However, in practice, many projects have opted not to do this, for a number of reasons, which -we now take a look at. +we now take a look at. Some of these may not be applicable to future new projects, +but some of them apply to all projects, old and new. Mismatch between package and module name ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -956,10 +957,8 @@ Package distributions Having two packages instead of one would increase the long-term maintenance cost of package distributions simply by virtue of the fact that two packages would -have to be released instead of one. To take the example of conda-forge, two -repositories would now be required, and the version pinning would need to be -updated manually every time. The metapackage could only be built once the core -package had been built and published, which would lengthen the release process. +have to be released instead of one, and in some cases this would introduce extra +manual work at each release. Synchronizing metadata ^^^^^^^^^^^^^^^^^^^^^^ @@ -985,8 +984,8 @@ Overall, this solution would imply a significantly higher maintenance burden, not just in terms of initial set-up and transition (which could already be prohibitive for large established projects), but also in terms of long-term maintenance. This also has the potential for breaking user workflows (in -particular around the issue of repositories, and e.g. uninstallation), so for -this reason we do not consider it a compelling alternative to the present PEP. +particular around the issue of repositories, and e.g. uninstallation). For all +these reasons, we do not consider it a compelling alternative to the present PEP. Syntax for deselecting extras ----------------------------- From 4b3a01098241f8bc12dbaaf0639273b15c97c1dc Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Sat, 31 May 2025 21:44:49 +0100 Subject: [PATCH 13/19] Apply suggestions from code review Co-authored-by: Carol Willing Co-authored-by: Pradyun Gedam --- peps/pep-0771.rst | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 2f1f93de781..0d2cc52b76b 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -94,7 +94,7 @@ recommend a default extra to install a backend or frontend include: * `glueviz `_: ``glueviz[qt]`` In all three cases, installing the package without any extras results in a -broken installation, and this is a commonly reported issue for some of these +broken installation, and this is a commonly reported support issue for some of these packages. Rationale @@ -214,7 +214,7 @@ once with no extras specified. An empty set of extras, such as ``package[]`` should be interpreted as meaning that the package should be installed *without* any default extras (unless -``package`` appears elsewhere in the dependency tree as mentioned above), so +``package`` appears elsewhere in the dependency tree as mentioned above). This would provide a universal way of obtaining a minimal installation of a package. We also note that some tools such as `pip`_ currently ignore unrecognized @@ -236,9 +236,9 @@ Finally, we note (as also discussed in `Relying on tooling to deselect any default extras`_) that package installers are allowed to implement their own options to control the above behavior, for example implementing an option that disables default extras for some or all packages regardless of where these -packages appear in the dependency tree -- although if such options are -implemented, they should be opt-in, and users should experience the above -behavior as default. +packages appear in the dependency tree. If such tool-specific options are +implemented, tool developers should make these opt-in, +and users should experience the above PEP 771 behavior as default. Examples -------- @@ -673,13 +673,9 @@ In essence, default extras should be considered just as 'weighty' as a required dependency. In some cases, if a package is widely used by many others, if it adds a default extra, then unless all downstream packages update their dependencies to specifically request a minimal installation, the defaults will -often end up getting installed. A concrete example of this is that the `pytest -`_ package has almost 1500 plugins at the time of -writing, all of which depend on pytest. If pytest was to start using a default -extra, it would need to consider this very carefully, as if the plugins are not -updated, installing any plugin will result in the default extra being -installed. This is not to say that it should not use default extras, but just -that the decision should be considered and planned carefully. +Default extras should generally be treated with the same "weight" as required dependencies. When a package is widely used, introducing a default extra will result in that extra's dependencies being transitively included -- unless all downstream packages are updated to explicitly opt out using minimal installation specifications. + +As an example, the `pytest `_ package currently has nearly 1,500 plugins that depend on it. If pytest were to add a default extra and those plugins were not updated accordingly, installing a plugin would include the default extras' dependencies. This doesn’t preclude the use of default extras, but addition of default extras requires careful evaluation of its downstream effects. Inheriting from default extras ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -752,7 +748,7 @@ Documenting packages with default extras ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Regardless of how default extras are used, package authors should aim to ensure -that the documentation for their package makes it clear how extras are to be +that their package's documentation makes it clear how extras are to be used. 'Best practices' documentation should mention: * that installing ``package`` will be equivalent to ``package[]`` From 641e7484013b3f8a7807f42eddc0ee1b0282fbd3 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Sat, 31 May 2025 21:48:39 +0100 Subject: [PATCH 14/19] Minor wording --- peps/pep-0771.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 0d2cc52b76b..07ef8646ad5 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -469,7 +469,8 @@ Packages with multiple kinds of defaults In some cases, it may be that packages need multiple kinds of defaults. As an example, in `Packages requiring at least one backend or frontend`_, we considered the case of packages that have *either* backends or frontends, but in some cases, packages may have to support -backends *and* frontends, and want to specify a default frontend and a default backend. +backends *and* frontends, and want to specify one or more default frontend and one or +more default backend. Ideally, one may want the following behavior: From 0a5069eba9f486192bb31be8fbc15972db0cd544 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 4 Jun 2025 13:34:59 +0100 Subject: [PATCH 15/19] Apply suggestions by @warsawnv --- peps/pep-0771.rst | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 07ef8646ad5..9a0b3fb5992 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -100,7 +100,7 @@ packages. Rationale ========= -A number of possible solutions have been extensively discussed by +A number of possible solutions have been discussed extensively by the community for several years, including in `this DPO thread `__ as well as in numerous issues and pull requests. The solution that is @@ -214,7 +214,8 @@ once with no extras specified. An empty set of extras, such as ``package[]`` should be interpreted as meaning that the package should be installed *without* any default extras (unless -``package`` appears elsewhere in the dependency tree as mentioned above). This +``package`` appears elsewhere in the dependency tree, in which case, the default +extra *would* be installed as mentioned above). This would provide a universal way of obtaining a minimal installation of a package. We also note that some tools such as `pip`_ currently ignore unrecognized @@ -300,7 +301,7 @@ meaning that installing: $ pip install astropy -would then also install optional but important optional dependencies such as +would then also install optional but recommended dependencies such as `scipy `_. Advanced users who want a minimal install could then use: @@ -483,14 +484,14 @@ Ideally, one may want the following behavior: $ pip install package[backend1, frontend2] # installs backend1 and frontend2 However, this PEP chooses not to provide a mechanism for making it so that e.g., if -``backend1`` is specified, this disabling the default backend but keeps the default -frontend, since this adds complexity. +``backend1`` is specified, the default backend would be disabled, but the +default frontend would be enabled, since this adds complexity. Maintainers should instead for now document that if a backend or frontend is explicitly specified, both backend and frontend need to be specified. Discoverability for users who want to do this should not be an issue however since users need to read the documentation in any case to find out what backends or frontends are -available, so they can be shown at the same time how do properly use the extras for +available, so they can be shown at the same time how to properly use the extras for backends and frontends. One option to increase user friendliness is that maintainers can create extras @@ -671,10 +672,14 @@ mean that all extras need to be defaults, and there is still scope for users to explicitly opt in to non-default extras. In essence, default extras should be considered just as 'weighty' as a required -dependency. In some cases, if a package is widely used by many others, if it +dependency. In some cases, if a package is widely used by many others and adds a default extra, then unless all downstream packages update their dependencies to specifically request a minimal installation, the defaults will -Default extras should generally be treated with the same "weight" as required dependencies. When a package is widely used, introducing a default extra will result in that extra's dependencies being transitively included -- unless all downstream packages are updated to explicitly opt out using minimal installation specifications. +Default extras should generally be treated with the same "weight" as required +dependencies. When a package is widely used, introducing a default extra will +result in that extra's dependencies being transitively included -- unless all +downstream packages are updated to explicitly opt out using minimal installation +specifications. As an example, the `pytest `_ package currently has nearly 1,500 plugins that depend on it. If pytest were to add a default extra and those plugins were not updated accordingly, installing a plugin would include the default extras' dependencies. This doesn’t preclude the use of default extras, but addition of default extras requires careful evaluation of its downstream effects. @@ -741,7 +746,7 @@ solved by changing the dependency tree to instead be:: └── package2 └── package1[] -assuming that ``package2`` indeed does not depend on any features provided by +assuming that indeed ``package2`` does not depend on any features provided by the extra dependencies of ``package1``. Authors therefore need to carefully consider a migration plan, coordinating with the authors of ``package2``. From 5605934624e050a409d947264a40eb4535da0e3f Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 4 Jun 2025 13:39:08 +0100 Subject: [PATCH 16/19] Avoid too many 'default's --- peps/pep-0771.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 9a0b3fb5992..f190a670ae8 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -510,11 +510,10 @@ This would allow (if desired) users to then get whatever the recommended backend is, even if that default changes in time. If there is a desire to implement a better solution in future, we believe this -PEP should not preclude this. For example, one could imagine in future adding the -ability for an extra to specify *which* default extras it disables rather than -disabling all default extras, but the default could still be for explicitly -specified extras to disable all default extras, which would be consistent with -the present PEP. +PEP should not preclude this. For example, one could imagine in future adding +the ability for an extra to specify *which* default extras it disables, and if +this is not specified then explicitly specified extras would disable all default +extras (consistent with the present PEP). Backward Compatibility ====================== From 18af74165960809f20081c0f0c7ad1233970de6f Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 4 Jun 2025 13:40:56 +0100 Subject: [PATCH 17/19] Explicitly state that for packages not using default extras, package[] will continue to be equivalent to package. --- peps/pep-0771.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index f190a670ae8..c8ecb268958 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -658,7 +658,9 @@ following recommendations would apply: installation even with older versions of packaging tools such as `pip`_, and releases of this package that pre-date the introduction of default extras for a specific package will also be installable with ``package[]`` (although in - these cases this will be equivalent to ``package``). + these cases this will be equivalent to ``package``). For packages that do not + define default extras, ``package[]`` will continue to be equivalent to + ``package``. Avoiding the addition of many default dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From e83c7f4f79f69e0facd3aa5a9ac1af6d551681b9 Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 4 Jun 2025 13:42:35 +0100 Subject: [PATCH 18/19] Fix broken paragraph --- peps/pep-0771.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index c8ecb268958..92de7def97b 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -672,10 +672,6 @@ installations and complicating dependency trees. Using default extras does not mean that all extras need to be defaults, and there is still scope for users to explicitly opt in to non-default extras. -In essence, default extras should be considered just as 'weighty' as a required -dependency. In some cases, if a package is widely used by many others and -adds a default extra, then unless all downstream packages update their -dependencies to specifically request a minimal installation, the defaults will Default extras should generally be treated with the same "weight" as required dependencies. When a package is widely used, introducing a default extra will result in that extra's dependencies being transitively included -- unless all From 2cdc79afdd456f6a057fae879025e76077e6b32d Mon Sep 17 00:00:00 2001 From: Thomas Robitaille Date: Wed, 4 Jun 2025 13:49:54 +0100 Subject: [PATCH 19/19] Spelling/grammar --- peps/pep-0771.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 92de7def97b..dfdc5af8897 100644 --- a/peps/pep-0771.rst +++ b/peps/pep-0771.rst @@ -301,7 +301,7 @@ meaning that installing: $ pip install astropy -would then also install optional but recommended dependencies such as +would then install optional but recommended dependencies such as `scipy `_. Advanced users who want a minimal install could then use: @@ -396,9 +396,9 @@ support the ability for users to opt-in to non-default extras, without removing default extras. Essentially, they might want: * ``package[]`` to give an installation without any extras -* ``package`` to install recommended dependencies (in a ``recommended`` extras) -* ``package[alternative]`` to not install default extras, but to install an alternative set of optional dependencies (in an ``alternative`` extras) -* ``package[additional]`` to install both recommended and additional dependencies (in an ``additional`` extras) +* ``package`` to install recommended dependencies (in a ``recommended`` extra) +* ``package[alternative]`` to not install default extras, but to install an alternative set of optional dependencies (in an ``alternative`` extra) +* ``package[additional]`` to install both recommended and additional dependencies (in an ``additional`` extra) This could be achieved with e.g: @@ -667,7 +667,7 @@ Avoiding the addition of many default dependencies One temptation for authors might be to include many dependencies by default since they can provide a way to opt out from these. We recommend however that authors -carefully consider what is included by default to avoid unecessarily bloating +carefully consider what is included by default to avoid unnecessarily bloating installations and complicating dependency trees. Using default extras does not mean that all extras need to be defaults, and there is still scope for users to explicitly opt in to non-default extras.