1
1
Fork 0
mirror of https://github.com/pypa/pip synced 2023-12-13 21:30:23 +01:00

Provide a better error message for a pyproject.toml editable install.

The message looks like this:

  File "setup.py" not found. Directory cannot be installed in editable
  mode: <absolute-dir-path>
  (A "pyproject.toml" file was found, but editable mode currently
  requires a setup.py based build.)
This commit is contained in:
Chris Jerdonek 2019-01-26 06:15:23 -08:00
parent e5f4bbb7dd
commit d619aba150
5 changed files with 59 additions and 14 deletions

2
news/6170.feature Normal file
View file

@ -0,0 +1,2 @@
Provide a better error message if attempting an editable install of a
directory with a ``pyproject.toml`` but no ``setup.py``.

View file

@ -2,6 +2,7 @@ from __future__ import absolute_import
import io
import os
import sys
from pip._vendor import pytoml, six
@ -20,6 +21,17 @@ def _is_list_of_str(obj):
)
def make_pyproject_path(setup_py_dir):
# type: (str) -> str
path = os.path.join(setup_py_dir, 'pyproject.toml')
# Python2 __file__ should not be unicode
if six.PY2 and isinstance(path, six.text_type):
path = path.encode(sys.getfilesystemencoding())
return path
def load_pyproject_toml(
use_pep517, # type: Optional[bool]
pyproject_toml, # type: str

View file

@ -23,6 +23,7 @@ from pip._internal.download import (
from pip._internal.exceptions import InstallationError
from pip._internal.models.index import PyPI, TestPyPI
from pip._internal.models.link import Link
from pip._internal.pyproject import make_pyproject_path
from pip._internal.req.req_install import InstallRequirement
from pip._internal.utils.misc import is_installable_dir
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@ -77,10 +78,18 @@ def parse_editable(editable_req):
if os.path.isdir(url_no_extras):
if not os.path.exists(os.path.join(url_no_extras, 'setup.py')):
raise InstallationError(
"Directory %r is not installable. File 'setup.py' not found." %
url_no_extras
msg = (
'File "setup.py" not found. Directory cannot be installed '
'in editable mode: {}'.format(os.path.abspath(url_no_extras))
)
pyproject_path = make_pyproject_path(url_no_extras)
if os.path.isfile(pyproject_path):
msg += (
'\n(A "pyproject.toml" file was found, but editable '
'mode currently requires a setup.py based build.)'
)
raise InstallationError(msg)
# Treating it as code that has already been checked out
url_no_extras = path_to_url(url_no_extras)

View file

@ -22,7 +22,7 @@ from pip._internal.locations import (
PIP_DELETE_MARKER_FILENAME, running_under_virtualenv,
)
from pip._internal.models.link import Link
from pip._internal.pyproject import load_pyproject_toml
from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path
from pip._internal.req.req_uninstall import UninstallPathSet
from pip._internal.utils.compat import native_str
from pip._internal.utils.hashes import Hashes
@ -471,13 +471,7 @@ class InstallRequirement(object):
# type: () -> str
assert self.source_dir, "No source dir for %s" % self
pp_toml = os.path.join(self.setup_py_dir, 'pyproject.toml')
# Python2 __file__ should not be unicode
if six.PY2 and isinstance(pp_toml, six.text_type):
pp_toml = pp_toml.encode(sys.getfilesystemencoding())
return pp_toml
return make_pyproject_path(self.setup_py_dir)
def load_pyproject_toml(self):
# type: () -> None

View file

@ -491,13 +491,41 @@ def test_install_from_local_directory_with_no_setup_py(script, data):
assert "Neither 'setup.py' nor 'pyproject.toml' found." in result.stderr
def test_editable_install_from_local_directory_with_no_setup_py(script, data):
def test_editable_install__local_dir_no_setup_py(
script, data, deprecated_python):
"""
Test installing from a local directory with no 'setup.py'.
Test installing in editable mode from a local directory with no setup.py.
"""
result = script.pip('install', '-e', data.root, expect_error=True)
assert not result.files_created
assert "is not installable. File 'setup.py' not found." in result.stderr
msg = result.stderr
if deprecated_python:
assert 'File "setup.py" not found. ' in msg
else:
assert msg.startswith('File "setup.py" not found. ')
assert 'pyproject.toml' not in msg
def test_editable_install__local_dir_no_setup_py_with_pyproject(
script, deprecated_python):
"""
Test installing in editable mode from a local directory with no setup.py
but that does have pyproject.toml.
"""
local_dir = script.scratch_path.join('temp').mkdir()
pyproject_path = local_dir.join('pyproject.toml')
pyproject_path.write('')
result = script.pip('install', '-e', local_dir, expect_error=True)
assert not result.files_created
msg = result.stderr
if deprecated_python:
assert 'File "setup.py" not found. ' in msg
else:
assert msg.startswith('File "setup.py" not found. ')
assert 'A "pyproject.toml" file was found' in msg
@pytest.mark.skipif("sys.version_info >= (3,4)")