Skip to content

Commit

Permalink
Improve editable_wheel debugging tips (#3822)
Browse files Browse the repository at this point in the history
  • Loading branch information
abravalheri committed Feb 13, 2023
2 parents c8a6a4a + e9c05e0 commit bc5f3c3
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 31 deletions.
3 changes: 3 additions & 0 deletions changelog.d/3822.misc.1.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added debugging tips for "editable mode" and update related docs.
Instead of using a custom exception to display the help message to the user,
``setuptools`` will now use a warning and re-raise the original exception.
5 changes: 5 additions & 0 deletions changelog.d/3822.misc.2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Added clarification about ``editable_wheel`` and ``dist_info`` CLI commands:
they should not be called directly with ``python setup.py ...`` instead they
are intended for internal use of ``setuptools`` (effectively as "private" commands).
Users are recommended to user build backend APIs (:pep:`517` and :pep:`660`)
in ``setuptools.build_meta``.
21 changes: 6 additions & 15 deletions docs/userguide/development_mode.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,16 +192,12 @@ works (still within the context of :pep:`660`).
Users are encouraged to try out the new editable installation techniques
and make the necessary adaptations.

If the ``compat`` mode does not work for you, you can also disable the
:pep:`editable install <660>` hooks in ``setuptools`` by setting an environment
variable:

.. code-block::
SETUPTOOLS_ENABLE_FEATURES="legacy-editable"
This *may* cause the installer (e.g. ``pip``) to effectively run the "legacy"
installation command: ``python setup.py develop`` [#installer]_.
.. note::
Newer versions of ``pip`` no longer run the fallback command
``python setup.py develop`` when the ``pyproject.toml`` file is present.
This means that setting the environment variable
``SETUPTOOLS_ENABLE_FEATURES="legacy-editable"``
will have no effect when installing a package with ``pip``.


How editable installations work
Expand Down Expand Up @@ -251,11 +247,6 @@ More information is available on the text of :pep:`PEP 660 <660#what-to-put-in-t
<https://blog.ganssle.io/articles/2019/08/test-as-installed.html>`_ for more
insights).
.. [#installer]
For this workaround to work, the installer tool needs to support legacy
editable installations. (Future versions of ``pip``, for example, may drop
support for this feature).
.. [#criteria]
``setuptools`` strives to find a balance between allowing the user to see
the effects of project files being edited while still trying to keep the
Expand Down
6 changes: 5 additions & 1 deletion setuptools/command/dist_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@


class dist_info(Command):
"""
This command is private and reserved for internal use of setuptools,
clients should use the ``setuptools.build_meta`` APIs.
"""

description = 'create a .dist-info directory'
description = "DO NOT CALL DIRECTLY, INTERNAL ONLY: create .dist-info directory"

user_options = [
('egg-base=', 'e', "directory containing .egg-info directories"
Expand Down
55 changes: 40 additions & 15 deletions setuptools/command/editable_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,11 @@ def convert(cls, mode: Optional[str]) -> "_EditableMode":

class editable_wheel(Command):
"""Build 'editable' wheel for development.
(This command is reserved for internal use of setuptools).
This command is private and reserved for internal use of setuptools,
clients should use the ``setuptools.build_meta`` APIs.
"""

description = "create a PEP 660 'editable' wheel"
description = "DO NOT CALL DIRECTLY, INTERNAL ONLY: create PEP 660 editable wheel"

user_options = [
("dist-dir=", "d", "directory to put final built distributions in"),
Expand Down Expand Up @@ -138,20 +139,11 @@ def run(self):
bdist_wheel.write_wheelfile(self.dist_info_dir)

self._create_wheel_file(bdist_wheel)
except Exception as ex:
except Exception:
traceback.print_exc()
msg = """
Support for editable installs via PEP 660 was recently introduced
in `setuptools`. If you are seeing this error, please report to:
https://github.com/pypa/setuptools/issues
Meanwhile you can try the legacy behavior by setting an
environment variable and trying to install again:
SETUPTOOLS_ENABLE_FEATURES="legacy-editable"
"""
raise errors.InternalError(cleandoc(msg)) from ex
project = self.distribution.name or self.distribution.get_name()
_DebuggingTips.warn(project)
raise

def _ensure_dist_info(self):
if self.dist_info_dir is None:
Expand Down Expand Up @@ -842,3 +834,36 @@ class InformationOnly(UserWarning):

class LinksNotSupported(errors.FileError):
"""File system does not seem to support either symlinks or hard links."""


class _DebuggingTips(InformationOnly):
@classmethod
def warn(cls, project: str):
msg = f"""An error happened while installing {project!r} in editable mode.
************************************************************************
The following steps are recommended to help debugging this problem:
- Try to install the project normally, without using the editable mode.
Does the error still persists?
(If it does, try fixing the problem before attempting the editable mode).
- If you are using binary extensions, make sure you have all OS-level
dependencies installed (e.g. compilers, toolchains, binary libraries, ...).
- Try the latest version of setuptools (maybe the error was already fixed).
- If you (or your project dependencies) are using any setuptools extension
or customization, make sure they support the editable mode.
After following the steps above, if the problem still persist and
you think this is related to how setuptools handles editable installations,
please submit a reproducible example
(see https://stackoverflow.com/help/minimal-reproducible-example) to:
https://github.com/pypa/setuptools/issues
More information about editable installs can be found in the docs:
https://setuptools.pypa.io/en/latest/userguide/development_mode.html
************************************************************************
"""
# We cannot use `add_notes` since pip hides PEP 678 notes
warnings.warn(msg, cls, stacklevel=2)
19 changes: 19 additions & 0 deletions setuptools/tests/test_editable_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from setuptools._importlib import resources as importlib_resources
from setuptools.command.editable_wheel import (
_DebuggingTips,
_LinkTree,
_find_virtual_namespaces,
_find_namespaces,
Expand Down Expand Up @@ -955,6 +956,24 @@ def test_distutils_leave_inplace_files(self, tmpdir_cwd):
assert any(name.endswith(ext) for ext in EXTENSION_SUFFIXES)


def test_debugging_tips(tmpdir_cwd, monkeypatch):
"""Make sure to display useful debugging tips to the user."""
jaraco.path.build({"module.py": "x = 42"})
dist = Distribution()
dist.script_name = "setup.py"
dist.set_defaults()
cmd = editable_wheel(dist)
cmd.ensure_finalized()

SimulatedErr = type("SimulatedErr", (Exception,), {})
simulated_failure = Mock(side_effect=SimulatedErr())
monkeypatch.setattr(cmd, "get_finalized_command", simulated_failure)

expected_msg = "following steps are recommended to help debugging"
with pytest.raises(SimulatedErr), pytest.warns(_DebuggingTips, match=expected_msg):
cmd.run()


def install_project(name, venv, tmp_path, files, *opts):
project = tmp_path / name
project.mkdir()
Expand Down

0 comments on commit bc5f3c3

Please sign in to comment.