Skip to content

Commit

Permalink
Support creating pyz files for different platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-blanchard committed May 8, 2018
1 parent d2be2e7 commit 398b84f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 25 deletions.
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
'click==6.7',
'pip>=9.0.1',
'importlib_resources>=0.4',
'wheel',
]

# The following template and classmethod are copied from
Expand Down
51 changes: 42 additions & 9 deletions src/shiv/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
import sys
import uuid

from collections import defaultdict
from configparser import ConfigParser
from pathlib import Path
from shutil import rmtree
from tempfile import TemporaryDirectory
from typing import Optional, List

import click

from wheel.install import WheelFile

from . import pip
from . import builder
from . import bootstrap
Expand Down Expand Up @@ -55,11 +59,9 @@ def validate_interpreter(interpreter_path: Optional[str] = None) -> Path:
interpreter_path
)

if real_path.exists():
return real_path

else:
sys.exit(INVALID_PYTHON.format(path=real_path))
if not real_path.exists():
print(INVALID_PYTHON.format(path=real_path))
return real_path


def copy_bootstrap(bootstrap_target: Path) -> None:
Expand All @@ -73,6 +75,28 @@ def copy_bootstrap(bootstrap_target: Path) -> None:
shutil.copyfile(f.absolute(), bootstrap_target / f.name)


def install_wheels(wheel_dir: Path, site_packages: Path) -> None:
"""Install wheels from wheel_dir into site_packages"""
to_install = [WheelFile(req) for req in wheel_dir.glob('*.whl')]

# We now have a list of wheels to install
print("Installing:")

# Ensure we always put stuff in site-packages no matter what
overrides = {
'purelib': str(site_packages),
'platlib': str(site_packages),
'headers': str(Path(site_packages, '..', 'headers')),
'scripts': str(Path(site_packages, '..', 'scripts')),
'data': str(Path(site_packages, '..', 'data')),
}
for wf in to_install:
print(" {}".format(wf.filename))
wf.install(force=True, overrides=overrides)
wf.zipfile.close()



@click.command(
context_settings=dict(
help_option_names=["-h", "--help", "--halp"], ignore_unknown_options=True
Expand Down Expand Up @@ -128,15 +152,24 @@ def main(
interpreter = validate_interpreter(python)

with TemporaryDirectory() as working_path:
wheel_dir = Path(working_path, "wheelhouse")
wheel_dir.mkdir(parents=True, exist_ok=True)

site_packages = Path(working_path, "site-packages")
site_packages.mkdir(parents=True, exist_ok=True)

# install deps into staged site-packages
pip.install(
python or sys.executable,
["--target", site_packages.as_posix()] + list(pip_args),
# download wheels into wheel_dir
pip.download(
sys.executable,
["--dest", str(wheel_dir)] + list(pip_args),
)

# install deps into staged site-packages
install_wheels(wheel_dir, site_packages)

# remove wheels
rmtree(str(wheel_dir))

# if entry_point is a console script, get the callable
if entry_point is None and console_script is not None:
try:
Expand Down
11 changes: 4 additions & 7 deletions src/shiv/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@
DISALLOWED_PIP_ARGS = "\nYou supplied a disallowed pip argument! '{arg}'\n\n{reason}\n"
NO_PIP_ARGS = "\nYou must supply PIP ARGS!\n"
NO_OUTFILE = "\nYou must provide an output file option! (--output-file/-o)\n"
INVALID_PYTHON = "\nInvalid python interpreter! {path} does not exist!\n"
INVALID_PYTHON = "\nInvalid python interpreter! {path} does not exist!\nThe output file will only work on a machine where this path exists.\n"
NO_ENTRY_POINT = "\nNo entry point '{entry_point}' found in the console_scripts!\n"
PIP_INSTALL_ERROR = "\nPip install failed!\n"
PIP_DOWNLOAD_ERROR = "\nPip download failed!\n"


# pip
PIP_INSTALL_ERROR = "\nPip install failed!\n"
PIP_REQUIRE_VIRTUALENV = "PIP_REQUIRE_VIRTUALENV"
BLACKLISTED_ARGS: Dict[Tuple[str, ...], str] = {
("-t", "--target"): "Shiv already supplies a target internally, so overriding is not allowed.",
("--editable", ): "Editable installs don't actually install via pip (they are just linked), so they are not allowed.",
("-d", "--download"): "Shiv needs to actually perform an install, not merely a download.",
("--user", "--root", "--prefix"): "Which conflicts with Shiv's internal use of '--target'.",
("-d", "--dest"): "Shiv already supplies a destination internally, so overriding is not allowed.",
}
15 changes: 6 additions & 9 deletions src/shiv/pip.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from typing import Generator, List

from .constants import PIP_REQUIRE_VIRTUALENV, PIP_INSTALL_ERROR
from .constants import PIP_REQUIRE_VIRTUALENV, PIP_DOWNLOAD_ERROR


@contextlib.contextmanager
Expand All @@ -25,25 +25,22 @@ def clean_pip_env() -> Generator[None, None, None]:
os.environ[PIP_REQUIRE_VIRTUALENV] = require_venv


def install(interpreter_path: str, args: List[str]) -> None:
"""`pip install` as a function.
def download(interpreter_path: str, args: List[str]) -> None:
"""`pip download` as a function.
Accepts a list of pip arguments.
.. code-block:: py
>>> install('/usr/local/bin/python3', ['numpy', '--target', 'site-packages'])
>>> download('/usr/local/bin/python3', ['numpy', '--dest', 'site-packages'])
Collecting numpy
Downloading numpy-1.13.3-cp35-cp35m-manylinux1_x86_64.whl (16.9MB)
100% || 16.9MB 53kB/s
Installing collected packages: numpy
Successfully installed numpy-1.13.3
"""
with clean_pip_env():

process = subprocess.Popen(
[interpreter_path, "-m", "pip", "--disable-pip-version-check", "install"] + args,
[interpreter_path, "-m", "pip", "--disable-pip-version-check", "download"] + args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
Expand All @@ -53,4 +50,4 @@ def install(interpreter_path: str, args: List[str]) -> None:
print(output.decode().rstrip())

if process.wait() > 0:
sys.exit(PIP_INSTALL_ERROR)
sys.exit(PIP_DOWNLOAD_ERROR)

0 comments on commit 398b84f

Please sign in to comment.