Commit 7ffca476 authored by Xavier Thompson's avatar Xavier Thompson

[feat] Use pip install --editable in easy_install.develop

Instead of running python setup.py develop directly. This will allow
using zc.buildout.easy_install.develop on recent projects that have
only a pyproject.toml. It also fixes develop leaving build artifacts
in the source directory that caused later runs to do nothing, e.g.
preventing develop-eggs to be rebuilt when a build dependency passed
in setup-eggs option of zc.recipe.egg:develop changed.

A verbosity parameter to tune verbosity of pip is added, with adjusted
values for the case of buildout:develop and of zc.recipe.egg:develop,
so as to remain close to the previous behavior with regards to logs.

Technical details:

For packages using PEP-660-style editable installs, supported by more
recent versions of pip, pip will not delegate to `setup.py develop` -
enabling editable installs for pure pyproject.toml projects - and will
instead generate a .dist-info metadata folder but not a .egg-link.

Since buildout currently requires a .egg-link, as it does not support
PEP 660's mechanism that relies on having a sites-packages directory,
we need to create this .egg-link after the fact. The tricky part is
finding out where the .egg-link should point: the path containing the
pyproject.toml, or a subdirectory?

For this we make use of *.dist-info/top_level.txt to first determine
the list of top-level packages, and then importlib to extract info
from the PEP-660-style install.

If top_level.txt does not exist, is empty, or otherwise does not list
any package that resolves to an import path, fallback to the path of
the folder that contains the pyproject.toml as the .egg-link target.
If it lists multiple packages that resolve to different import paths,
arbitrarily use the first one and emit a warning.

Support namespace packages where `spec.submodule_search_locations` is
a `_NamespacePath` object instead of a simple `list` and also support
cases where the layout of the source project does not follow the same
structure as the package tree - meaning some custom magic might be
involved in making editable imports work as intended.
parent c60ddacb
...@@ -1131,7 +1131,8 @@ class Buildout(DictMixin): ...@@ -1131,7 +1131,8 @@ class Buildout(DictMixin):
for setup in files: for setup in files:
self._logger.info("Develop: %r", setup) self._logger.info("Develop: %r", setup)
__doing__ = 'Processing develop directory %r.', setup __doing__ = 'Processing develop directory %r.', setup
zc.buildout.easy_install.develop(setup, dest) zc.buildout.easy_install.develop(setup, dest,
verbosity=-20)
except: except:
# if we had an error, we need to roll back changes, by # if we had an error, we need to roll back changes, by
# removing any files we created. # removing any files we created.
......
This diff is collapsed.
...@@ -348,7 +348,7 @@ reporting that a version was picked automatically: ...@@ -348,7 +348,7 @@ reporting that a version was picked automatically:
zc.buildout.easy_install DEBUG zc.buildout.easy_install DEBUG
Fetching demoneeded 1.1 from: http://.../demoneeded-1.1.zip Fetching demoneeded 1.1 from: http://.../demoneeded-1.1.zip
zc.buildout.easy_install DEBUG zc.buildout.easy_install DEBUG
Running pip install:... Running pip wheel...
zc.buildout.easy_install INFO zc.buildout.easy_install INFO
Got demoneeded 1.1. Got demoneeded 1.1.
zc.buildout.easy_install DEBUG zc.buildout.easy_install DEBUG
......
...@@ -204,8 +204,7 @@ We should be able to deal with setup scripts that aren't setuptools based. ...@@ -204,8 +204,7 @@ We should be able to deal with setup scripts that aren't setuptools based.
... # doctest: +ELLIPSIS ... # doctest: +ELLIPSIS
Installing... Installing...
Develop: '/sample-buildout/foo' Develop: '/sample-buildout/foo'
... Running pip install --editable /sample-buildout/foo
Installed /sample-buildout/foo
... ...
>>> ls('develop-eggs') >>> ls('develop-eggs')
...@@ -216,10 +215,9 @@ We should be able to deal with setup scripts that aren't setuptools based. ...@@ -216,10 +215,9 @@ We should be able to deal with setup scripts that aren't setuptools based.
... # doctest: +ELLIPSIS ... # doctest: +ELLIPSIS
Installing... Installing...
Develop: '/sample-buildout/foo' Develop: '/sample-buildout/foo'
in: '/sample-buildout/foo' Running pip install --editable /sample-buildout/foo
... -q develop -mN -d /sample-buildout/develop-eggs/... ... -m pip install -t ... --editable /sample-buildout/foo
...
""" """
def buildout_error_handling(): def buildout_error_handling():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment