Commit 64f61417 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. For this we make use
of importlib to extract info from the PEP-660-style install.

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.

Allow for entries in top_level.txt that are not actually packages,
i.e. where importlib.util.find_spec().submodule_search_locations is
None. A test is added for this case.
parent 7e9b8c93
......@@ -1131,7 +1131,8 @@ class Buildout(DictMixin):
for setup in files:
self._logger.info("Develop: %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:
# if we had an error, we need to roll back changes, by
# removing any files we created.
......
This diff is collapsed.
......@@ -348,7 +348,7 @@ reporting that a version was picked automatically:
zc.buildout.easy_install DEBUG
Fetching demoneeded 1.1 from: http://.../demoneeded-1.1.zip
zc.buildout.easy_install DEBUG
Running pip install:...
Running pip wheel...
zc.buildout.easy_install INFO
Got demoneeded 1.1.
zc.buildout.easy_install DEBUG
......
......@@ -204,8 +204,7 @@ We should be able to deal with setup scripts that aren't setuptools based.
... # doctest: +ELLIPSIS
Installing...
Develop: '/sample-buildout/foo'
...
Installed /sample-buildout/foo
Running pip install --editable /sample-buildout/foo
...
>>> ls('develop-eggs')
......@@ -216,10 +215,9 @@ We should be able to deal with setup scripts that aren't setuptools based.
... # doctest: +ELLIPSIS
Installing...
Develop: '/sample-buildout/foo'
in: '/sample-buildout/foo'
... -q develop -mN -d /sample-buildout/develop-eggs/...
Running pip install --editable /sample-buildout/foo
... -m pip install -t ... --editable /sample-buildout/foo
...
"""
def buildout_error_handling():
......@@ -1157,6 +1155,47 @@ existing setup.cfg:
"""
def develop_pyproject_only_without_package():
"""
Install a pyproject-only project that does not contain any package,
but only a single module.
>>> mkdir('nopkg')
>>> write('nopkg', 'pyproject.toml', '''
... ''')
>>> write('nopkg', 'xnopkg.py', '''
... print('nopkg')
... ''')
>>> write('buildout.cfg', '''
... [buildout]
... develop = nopkg
... parts =
... ''')
>>> print_(system((join('bin', 'buildout'), '-vv')), end='')
Develop: '/sample-buildout/nopkg'
Found no package import path in develop project /sample-buildout/nopkg for packages ('xnopkg',)
Falling back to project's root directory
>>> ls('develop-eggs')
- xnopkg.egg-link
- zc.recipe.egg.egg-link
>>> cat('develop-eggs/xnopkg.egg-link')
/sample-buildout/nopkg
"""
# BBB Python2: skip PEP 660 test
# Whether the test succeeds actually depends on pip and setuptools versions
# supporting PEP 660, but Python2 is the reason they would be stuck at old
# versions, so it will always fail with Python2, and Python3 should use more
# recent versions.
if sys.version_info < (3,):
del develop_pyproject_only_without_package
def uninstall_recipes_used_for_removal():
r"""
Uninstall recipes need to be called when a part is removed too:
......
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