Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates to PEP 660 #1978

Merged
merged 17 commits into from
Jun 21, 2021
Merged
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 42 additions & 4 deletions pep-0660.rst
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,11 @@ Build-backends must produce wheels that have the same dependencies
with the exception that they can add dependencies necessary for their editable
mechanism to function at runtime (such as `editables`_).

The filename for the editable wheel needs to be PEP 427 compliant too. It
The filename for the "editable" wheel needs to be PEP 427 compliant too. It
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Goodbye unicode quotes. I notice a lack of emoji in the PEP as well.

does not need to use the same tags as ``build_wheel`` but it must be tagged as
compatible with the system.

An editable wheel uses the wheel format not for distribution but as ephemeral
An "editable" wheel uses the wheel format not for distribution but as ephemeral
communication between the build system and the front end. This avoids having
the build backend install anything directly. This wheel must not be exposed
to end users, nor cached, nor distributed.
Expand All @@ -142,7 +142,8 @@ If not defined, the default implementation is equivalent to ``return []``.
What to put in the wheel
------------------------

Build backends may use different techniques to achive the goals of an editable
Build backends must populate the generated wheel with files that when installed will result in an editable install.
Build backends may use different techniques to achieve the goals of an editable
install. This section provides examples and is not normative.

* Build backends may choose to place a ``.pth`` file at the root of the ``.whl`` file,
Expand All @@ -157,11 +158,16 @@ install. This section provides examples and is not normative.
a path importable, often including the project's own ``setup.py`` and other
scripts that would not be part of a normal installation. The proxy strategy
can achieve a higher level of fidelity than path-based methods.
* Symbolic links are another useful mechanism to realize editable installs.
Since, at the time this writing, the ``wheel`` specification does not support
symbolic links, they are not directly usable. It is however possible to defer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems very magical, and like a hack to me. As an end-user would definitely be surprised to discover this unexpected side-effect when first running my application. Also, I think this would run into issues with resource files where the user is not using importlib.resources but pkg_resources 🤔 Because then you might need to trigger the symlink before a module alongside is actually imported, not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure it's a hack. With an executable .pth it works reliably though. To be honest and blunt, all concepts we are discussing for editables sound like hacks to me (except a .pth that exposes a whole directory).

Copy link
Contributor

@gaborbernat gaborbernat Jun 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The backend generating files into the target interpreter post-installation seems like a nightmare for a frontend. All of a sudden has no idea what files it needs to uninstall. This would be a no go for me as a frontend developer. If anything I'd prefer to explicitly ban this in the PEP to provide some sanity for the frontend developers. I think the only type of operation a backend is allowed in the target interpreter is a read and update; create+delete should be prohibited.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added another approach to handle symbolic links.

the creation of symbolic links to an import hook or executable ``.pth`` that
the backend adds in the "editable" wheel.

Frontend requirements
---------------------

Frontends must install editable wheels in the same way as regular wheels.
Frontends must install "editable" wheels in the same way as regular wheels.
This also means uninstallation of editables does not require any special treatment.

Frontends must create a ``direct_url.json`` file in the ``.dist-info``
Expand Down Expand Up @@ -189,12 +195,44 @@ cached nor distributed.
Rejected ideas
==============

``editable`` local version identifier
-------------------------------------

The ideas of having build backends append or modify the local version
identifier to include the ``editable`` string has been rejected because it
would not satisfy ``==`` version speicifier that include the local version
identifier. In other workds ``pkg==1.0+local`` is not satisfied by version
``1.0+local.editable``.

Virtual wheel
-------------

`Another approach was proposed <https://github.com/pypa/pip/pull/8215>`_, where
the build backend returns a mapping from source files and directories to the
installed layout. It is then up to the installer frontend to realize the
editable installation by whatever mean it deems adequate for its users.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

means


In terms of capabilities, both proposals seem equivalent, at least in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're going with this bold statement do clarify how you're planning to support headers, data files and scripts.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should I? The whole point is that we don't know (in either proposal) and can let backend authors experiment.

Regarding headers, for instance, assuming there is a use case to install them in editable mode, one can use symlinks. But is there such a use case ? This PEP explicitly says only python files must be "edtiables" and changes to other file may require an additional installation step.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about scripts? Those can be python files.

Regarding headers, for instance, assuming there is a use case to install them in editable mode, one can use symlinks. But is there such a use case?

Check astropy project that ships headers. The wheel spec allows it so there is a such use case.

Why should I? The whole point is that we don't know (in either proposal) and can let backend authors experiment.

We should at least hypothetically provide a way to achieve this, just to prove that the PEP allows that functionality.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pypa/pip#8215 doesn't seem related to this PEP.

We also rejected my prototype that uses the wheel structure but skips creating an archive. The archive is easy to produce; no one has to worry about cleaning a build directory (full of the unpacked wheel); we avoid describing exactly what an unpacked wheel is.

I think packages that link against other packages that provide headers are used to being able to find those headers in source checkouts, as well as in the installed location? I don't think the way installed headers work in Python is particularly great.

Most scripts are entry_points scripts handled by the standard wheel install.

setup.py develop is about making your code importable by other code, and providing your metadata so that your editable distribution is "installed" according to "pip list".

But old-fashioned scripts are standalone. They need to import library code, but almost never need to be "imported by" dependents. There is less pressure to copy them to the central scripts location during an editable install. If you really are editing, you may run those scripts directly from the checkout. They will work fine.

Data files are almost always relative to the source code (part of purelib/platlib) since unfortunately the data_files feature has been broken for a long time. It does not install into a predictable location given varying virtualenv / --user / global install targets.

This is a long way to say that we think the most important use case is covered without worrying about scripts, headers, and data. It's hard to manually do an in-place build with correct .dist-info metadata on the .dist-info search path. setup.py develop or a replacement editable system solves that.

Could line 218 be reworded to say something more like "both proposals could provide the core 'editable' feature".

My biggest concern with the virtual wheel proposal is that build systems do not work by generating the necessary mapping as an intermediate step. Providing it to the hook could be burdensome and restrict the design of 'editable-capable' build systems. And that while it's pretty obvious to see how the simple case would work, it would still be the installer's responsibility to make sense of whatever crazy mapping was provided to it by the backend - if the structure of the mapping did not resemble the structure of what was on disk?

In this PEP and in setup.py develop the publisher has an incentive to lay out their source code in a way that would (mostly) work with a normal .pth file.

principle.

At the time of writing this PEP, it is clear that the community has a wide
range of theoretical and practical expectations about editable installs. The
reality is that the only one there is wide experience with is path insertion
via .pth (i.e. what setup.py develop does).

We believe that PEP 660 better addresses these "unknown unknowns" today in the
most reliable way, in by letting project authors select or implement the
backend that provides the editable mechanism that best suit their requirements.
Since the frontend has no latitude in *how* to install the "editable" wheel, in
case of issue, there is only one place to investigate: the build backend.

With the competing proposal, issues need to be investigated in the frontend,
the backend and possiblty the specification. There is also a high probability
that different frontends, implementing the specification in different ways,
will produce installations that behave differently than project authors
intended, creating confusion, or worse, projects that only work with specific
frontends.

References
==========

Expand Down