1import subprocess 2from textwrap import dedent 3 4import pytest 5import jaraco.envs 6import path 7 8 9@pytest.fixture 10def venv(tmp_path, setuptools_wheel): 11 env = jaraco.envs.VirtualEnv() 12 vars(env).update( 13 root=path.Path(tmp_path), # workaround for error on windows 14 name=".venv", 15 create_opts=["--no-setuptools"], 16 req=str(setuptools_wheel), 17 ) 18 return env.create() 19 20 21EXAMPLE = { 22 'pyproject.toml': dedent("""\ 23 [build-system] 24 requires = ["setuptools", "wheel"] 25 build-backend = "setuptools.build_meta" 26 27 [project] 28 name = "mypkg" 29 version = "3.14159" 30 license = {text = "MIT"} 31 description = "This is a Python package" 32 dynamic = ["readme"] 33 classifiers = [ 34 "Development Status :: 5 - Production/Stable", 35 "Intended Audience :: Developers" 36 ] 37 urls = {Homepage = "http://github.com"} 38 dependencies = ['importlib-metadata; python_version<"3.8"'] 39 40 [tool.setuptools] 41 package-dir = {"" = "src"} 42 packages = {find = {where = ["src"]}} 43 license-files = ["LICENSE*"] 44 45 [tool.setuptools.dynamic] 46 readme = {file = "README.rst"} 47 48 [tool.distutils.egg_info] 49 tag-build = ".post0" 50 """), 51 "MANIFEST.in": dedent("""\ 52 global-include *.py *.txt 53 global-exclude *.py[cod] 54 """).strip(), 55 "README.rst": "This is a ``README``", 56 "LICENSE.txt": "---- placeholder MIT license ----", 57 "src": { 58 "mypkg": { 59 "__init__.py": dedent("""\ 60 import sys 61 62 if sys.version_info[:2] >= (3, 8): 63 from importlib.metadata import PackageNotFoundError, version 64 else: 65 from importlib_metadata import PackageNotFoundError, version 66 67 try: 68 __version__ = version(__name__) 69 except PackageNotFoundError: 70 __version__ = "unknown" 71 """), 72 "__main__.py": dedent("""\ 73 from importlib.resources import read_text 74 from . import __version__, __name__ as parent 75 from .mod import x 76 77 data = read_text(parent, "data.txt") 78 print(__version__, data, x) 79 """), 80 "mod.py": "x = ''", 81 "data.txt": "Hello World", 82 } 83 } 84} 85 86 87SETUP_SCRIPT_STUB = "__import__('setuptools').setup()" 88MISSING_SETUP_SCRIPT = pytest.param( 89 None, 90 marks=pytest.mark.xfail( 91 reason="Editable install is currently only supported with `setup.py`" 92 ) 93) 94 95 96@pytest.mark.parametrize("setup_script", [SETUP_SCRIPT_STUB, MISSING_SETUP_SCRIPT]) 97def test_editable_with_pyproject(tmp_path, venv, setup_script): 98 project = tmp_path / "mypkg" 99 files = {**EXAMPLE, "setup.py": setup_script} 100 project.mkdir() 101 jaraco.path.build(files, prefix=project) 102 103 cmd = [venv.exe(), "-m", "pip", "install", 104 "--no-build-isolation", # required to force current version of setuptools 105 "-e", str(project)] 106 print(str(subprocess.check_output(cmd), "utf-8")) 107 108 cmd = [venv.exe(), "-m", "mypkg"] 109 assert subprocess.check_output(cmd).strip() == b"3.14159.post0 Hello World" 110 111 (project / "src/mypkg/data.txt").write_text("foobar") 112 (project / "src/mypkg/mod.py").write_text("x = 42") 113 assert subprocess.check_output(cmd).strip() == b"3.14159.post0 foobar 42" 114