diff --git a/peps/pep-0771.rst b/peps/pep-0771.rst index 5755afc377c..2f1f93de781 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 @@ -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,19 +67,19 @@ 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 -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 ------------------------- @@ -213,9 +212,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 +228,17 @@ 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. + +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 -------- @@ -263,9 +250,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 +271,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 +289,6 @@ retain the ability to install only the strictly required dependencies: ] [project.optional-dependencies] - minimal = [] recommended = [ "scipy", "..." @@ -333,14 +300,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 +338,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 +387,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 +409,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 +441,6 @@ configuration would solve this case: ] [project.optional-dependencies] - minimal = [] recommended = [ "scipy", "..." @@ -500,6 +463,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 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 +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 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. Backward Compatibility ====================== @@ -540,10 +553,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 @@ -567,6 +580,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 ===================== @@ -626,28 +646,18 @@ 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. -* 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -659,15 +669,27 @@ 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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 +730,40 @@ 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] + └── 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``. -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``. +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 -------------------------------- @@ -778,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. @@ -787,6 +821,172 @@ 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. 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 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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, and in some cases this would introduce extra +manual work at each release. + +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). For all +these reasons, we do not consider it a compelling alternative to the present PEP. + Syntax for deselecting extras ----------------------------- @@ -846,7 +1046,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. @@ -890,49 +1089,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. - -``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. +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 =========