Skip to content

Commit

Permalink
Fixed --editable install for setuptools projects without setup.py.
Browse files Browse the repository at this point in the history
Co-Authored-By: Tzu-ping Chung <uranusjr@gmail.com>
Co-Authored-By: Pradyun Gedam <3275593+pradyunsg@users.noreply.github.com>
  • Loading branch information
3 people committed Mar 3, 2021
1 parent d9d7790 commit 7a95720
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 17 deletions.
1 change: 1 addition & 0 deletions news/9547.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for editable installs for project with only setup.cfg files.
11 changes: 7 additions & 4 deletions src/pip/_internal/req/constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,19 @@ def parse_editable(editable_req):
url_no_extras, extras = _strip_extras(url)

if os.path.isdir(url_no_extras):
if not os.path.exists(os.path.join(url_no_extras, 'setup.py')):
setup_py = os.path.join(url_no_extras, 'setup.py')
setup_cfg = os.path.join(url_no_extras, 'setup.cfg')
if not os.path.exists(setup_py) and not os.path.exists(setup_cfg):
msg = (
'File "setup.py" not found. Directory cannot be installed '
'in editable mode: {}'.format(os.path.abspath(url_no_extras))
'File "setup.py" or "setup.cfg" 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.)'
'mode currently requires a setuptools-based build.)'
)
raise InstallationError(msg)

Expand Down
8 changes: 5 additions & 3 deletions src/pip/_internal/utils/setuptools_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
# invoking via the shim. This avoids e.g. the following manifest_maker
# warning: "warning: manifest_maker: standard file '-c' not found".
_SETUPTOOLS_SHIM = (
"import sys, setuptools, tokenize; sys.argv[0] = {0!r}; __file__={0!r};"
"f=getattr(tokenize, 'open', open)(__file__);"
"code=f.read().replace('\\r\\n', '\\n');"
"import io, os, sys, setuptools, tokenize; sys.argv[0] = {0!r}; __file__={0!r};"
"f = getattr(tokenize, 'open', open)(__file__) "
"if os.path.exists(__file__) "
"else io.StringIO('from setuptools import setup; setup()');"
"code = f.read().replace('\\r\\n', '\\n');"
"f.close();"
"exec(compile(code, __file__, 'exec'))"
)
Expand Down
40 changes: 30 additions & 10 deletions tests/functional/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -641,9 +641,9 @@ def test_editable_install__local_dir_no_setup_py(

msg = result.stderr
if deprecated_python:
assert 'File "setup.py" not found. ' in msg
assert 'File "setup.py" or "setup.cfg" not found. ' in msg
else:
assert msg.startswith('ERROR: File "setup.py" not found. ')
assert msg.startswith('ERROR: File "setup.py" or "setup.cfg" not found. ')
assert 'pyproject.toml' not in msg


Expand All @@ -663,9 +663,9 @@ def test_editable_install__local_dir_no_setup_py_with_pyproject(

msg = result.stderr
if deprecated_python:
assert 'File "setup.py" not found. ' in msg
assert 'File "setup.py" or "setup.cfg" not found. ' in msg
else:
assert msg.startswith('ERROR: File "setup.py" not found. ')
assert msg.startswith('ERROR: File "setup.py" or "setup.cfg" not found. ')
assert 'A "pyproject.toml" file was found' in msg


Expand Down Expand Up @@ -1034,15 +1034,13 @@ def test_install_package_with_prefix(script, data):
result.did_create(install_path)


def test_install_editable_with_prefix(script):
def _test_install_editable_with_prefix(script, files):
# make a dummy project
pkga_path = script.scratch_path / 'pkga'
pkga_path.mkdir()
pkga_path.joinpath("setup.py").write_text(textwrap.dedent("""
from setuptools import setup
setup(name='pkga',
version='0.1')
"""))

for fn, contents in files.items():
pkga_path.joinpath(fn).write_text(textwrap.dedent(contents))

if hasattr(sys, "pypy_version_info"):
site_packages = os.path.join(
Expand Down Expand Up @@ -1087,6 +1085,28 @@ def test_install_editable_with_target(script):
result.did_create(script.scratch / 'target' / 'watching_testrunner.py')


def test_install_editable_with_prefix_setup_py(script):
setup_py = """
from setuptools import setup
setup(name='pkga', version='0.1')
"""
_test_install_editable_with_prefix(script, {"setup.py": setup_py})


def test_install_editable_with_prefix_setup_cfg(script):
setup_cfg = """[metadata]
name = pkga
version = 0.1
"""
pyproject_toml = """[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
"""
_test_install_editable_with_prefix(
script, {"setup.cfg": setup_cfg, "pyproject.toml": pyproject_toml}
)


def test_install_package_conflict_prefix_and_user(script, data):
"""
Test installing a package using pip install --prefix --user errors out
Expand Down

0 comments on commit 7a95720

Please sign in to comment.