From b897d4ae8c48dffa01a27b4b8a0af70c50a8f060 Mon Sep 17 00:00:00 2001 From: Ian MacLean Date: Sun, 29 Jul 2018 10:46:17 +0900 Subject: [PATCH 1/8] Added more informative output - show the args shiv will be using - Notify the user which output file was written and if an automatic entry point has been applied - color the ouput from pip in blue to distinguish it from whats coming from shiv. Matches Pipenv for familiararity - Fixes #42 --- .gitignore | 2 ++ setup.py | 2 ++ src/shiv/cli.py | 54 ++++++++++++++++++++++++++++++++++--------------- src/shiv/pip.py | 7 +++++-- 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 386ec0d..b6ac725 100644 --- a/.gitignore +++ b/.gitignore @@ -59,6 +59,8 @@ target/ .python-version .pytest_cache/ venv/ +.venv +.vscode activate # mypy diff --git a/setup.py b/setup.py index 52b443f..c8d67c4 100644 --- a/setup.py +++ b/setup.py @@ -16,6 +16,8 @@ 'click==6.7', 'pip>=9.0.1', 'importlib_resources>=0.4', + 'crayons>=0.1.2', + 'blindspin>=2.0.1' ] # The following template and classmethod are copied from diff --git a/src/shiv/cli.py b/src/shiv/cli.py index 285cdf2..71d771a 100644 --- a/src/shiv/cli.py +++ b/src/shiv/cli.py @@ -9,6 +9,8 @@ from typing import Optional, List import click +import crayons +from blindspin import spinner from . import pip from . import builder @@ -87,28 +89,35 @@ def main( quiet = "-q" in pip_args or '--quiet' in pip_args if not quiet: - click.secho(" shiv! " + SHIV, bold=True) + click.secho("shiv! " + SHIV, bold=True) if not pip_args: - sys.exit(NO_PIP_ARGS) + sys.exit(crayons.red(NO_PIP_ARGS)) if output_file is None: - sys.exit(NO_OUTFILE) + sys.exit(crayons.red(NO_OUTFILE)) # check for disallowed pip arguments for blacklisted_arg in BLACKLISTED_ARGS: for supplied_arg in pip_args: if supplied_arg in blacklisted_arg: - sys.exit( + sys.exit(crayons.red( DISALLOWED_PIP_ARGS.format( arg=supplied_arg, reason=BLACKLISTED_ARGS[blacklisted_arg] - ) + )) ) - + if not quiet: + click.secho("with args : \n\toutput file : '{}', \n\tentry point : '{}', \ + \n\tpython : '{}', \n\tcompressed : {}" + .format(output_file, entry_point or '', python or sys.executable, compressed)) + click.secho("\tpip args '{}' ".format(' '.join(pip_args))) with TemporaryDirectory() as working_path: site_packages = Path(working_path, "site-packages") site_packages.mkdir(parents=True, exist_ok=True) + if not quiet: + click.secho("Pip installing dependencies to {}...".format(site_packages), bold=True) + # install deps into staged site-packages pip.install( ["--target", site_packages.as_posix()] + list(pip_args), @@ -118,8 +127,10 @@ def main( if entry_point is None and console_script is not None: try: entry_point = find_entry_point(site_packages, console_script) + if not quiet: + click.secho("Discovered entry point '{}'".format(entry_point)) except KeyError: - sys.exit(NO_ENTRY_POINT.format(entry_point=console_script)) + sys.exit(crayons.red(NO_ENTRY_POINT.format(entry_point=console_script))) # create runtime environment metadata env = Environment( @@ -133,17 +144,28 @@ def main( bootstrap_target = Path(working_path, "_bootstrap") bootstrap_target.mkdir(parents=True, exist_ok=True) + if not quiet: + click.secho("Injecting bootstrap code") # copy bootstrap code copy_bootstrap(bootstrap_target) - # create the zip - builder.create_archive( - Path(working_path), - target=Path(output_file), - interpreter=python or sys.executable, - main="_bootstrap:bootstrap", - compressed=compressed, - ) + if not quiet: + click.secho("Creating zip archive") + + with spinner(): + # create the zip + builder.create_archive( + Path(working_path), + target=Path(output_file), + interpreter=python or sys.executable, + main="_bootstrap:bootstrap", + compressed=compressed, + ) if not quiet: - click.secho(" done ", bold=True) + conf_message = "Done, wrote output file to '{}'".format(output_file) + if entry_point: + conf_message += ", entry point is '{}'".format(entry_point) + else: + conf_message += ", no entry point specified." + click.secho(conf_message, bold=True) diff --git a/src/shiv/pip.py b/src/shiv/pip.py index 8ab2a4c..3dbc213 100644 --- a/src/shiv/pip.py +++ b/src/shiv/pip.py @@ -3,6 +3,9 @@ import subprocess import sys +import click +import crayons + from pathlib import Path from typing import Generator, List @@ -67,7 +70,7 @@ def install(args: List[str]) -> None: for output in process.stdout: if output: - print(output.decode().rstrip()) + click.echo(crayons.blue(output.decode().rstrip())) if process.wait() > 0: - sys.exit(PIP_INSTALL_ERROR) + sys.exit(crayons.red(PIP_INSTALL_ERROR)) From 1eb7eb9ad996381c1e2723d1e176bbee9140698a Mon Sep 17 00:00:00 2001 From: Ian MacLean Date: Sun, 29 Jul 2018 11:14:47 +0900 Subject: [PATCH 2/8] Add flags to mypy for tox tests to pass - --ignore-missing-imports looks required for deps with no typedefs. --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 94f264d..41cd9a0 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,7 @@ envlist = py36 passenv = TRAVIS TRAVIS_* commands= py.test --cov=shiv - mypy src/ + mypy --ignore-missing-imports src/ flake8 src/ test/ deps= pytest From 89c86d0f2e04d461d05fbec0dc89dfe9222b9c5d Mon Sep 17 00:00:00 2001 From: Ian MacLean Date: Fri, 17 Aug 2018 08:23:22 +0900 Subject: [PATCH 3/8] fixed flake8 errors --- src/shiv/pip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shiv/pip.py b/src/shiv/pip.py index 2c378e5..7f817cb 100644 --- a/src/shiv/pip.py +++ b/src/shiv/pip.py @@ -5,11 +5,11 @@ import click import crayons -from pathlib import Path from typing import Generator, List from .constants import PIP_REQUIRE_VIRTUALENV, PIP_INSTALL_ERROR + @contextlib.contextmanager def clean_pip_env() -> Generator[None, None, None]: """A context manager for temporarily removing 'PIP_REQUIRE_VIRTUALENV' from the environment. From 32b3b89beb0e3f4b04024ca04efa17226e55b380 Mon Sep 17 00:00:00 2001 From: Ian MacLean Date: Wed, 8 May 2019 00:04:08 +0900 Subject: [PATCH 4/8] Simplified output and added --verbose flag. --- .gitignore | 6 +++- src/shiv/cli.py | 83 ++++++++++++++++++------------------------------- src/shiv/pip.py | 11 ++----- 3 files changed, 38 insertions(+), 62 deletions(-) diff --git a/.gitignore b/.gitignore index b6ac725..b2668f2 100644 --- a/.gitignore +++ b/.gitignore @@ -60,8 +60,12 @@ target/ .pytest_cache/ venv/ .venv -.vscode activate # mypy .mypy_cache +None/ + +# IDE +.vscode +pyrightconfig.json diff --git a/src/shiv/cli.py b/src/shiv/cli.py index 17aebff..533f412 100644 --- a/src/shiv/cli.py +++ b/src/shiv/cli.py @@ -8,13 +8,12 @@ import importlib_resources # type: ignore from configparser import ConfigParser +from datetime import datetime from pathlib import Path from tempfile import TemporaryDirectory from typing import Optional, List, no_type_check import click -import crayons -from blindspin import spinner from . import pip from . import builder @@ -117,6 +116,11 @@ def _interpreter_path(append_version: bool = False) -> str: default=True, help="Whether or not to compress your zip.", ) +@click.option( + "--verbose/--quiet", + default=False, + help="Whether or not to generate versose output.", +) @click.option( "--compile-pyc/--no-compile-pyc", default=False, @@ -133,6 +137,7 @@ def main( console_script: Optional[str], python: Optional[str], site_packages: Optional[str], + verbose: bool, compressed: bool, compile_pyc: bool, extend_pythonpath: bool, @@ -142,38 +147,27 @@ def main( Shiv is a command line utility for building fully self-contained Python zipapps as outlined in PEP 441, but with all their dependencies included! """ - - quiet = "-q" in pip_args or '--quiet' in pip_args - if not quiet: - click.secho("shiv! " + SHIV, bold=True) - - if not pip_args: - sys.exit(crayons.red(NO_PIP_ARGS)) - - if not pip_args and not site_packages: sys.exit(NO_PIP_ARGS_OR_SITE_PACKAGES) + + #verbose = "-v" in pip_args or '--verbose' in pip_args + if verbose: + click.secho("shiv! ", bold=True) if output_file is None: - sys.exit(crayons.red(NO_OUTFILE)) + sys.exit(NO_OUTFILE) # check for disallowed pip arguments for disallowed in DISALLOWED_ARGS: for supplied_arg in pip_args: - - if supplied_arg in blacklisted_arg: - sys.exit(crayons.red( - DISALLOWED_PIP_ARGS.format( - arg=supplied_arg, reason=BLACKLISTED_ARGS[blacklisted_arg] - )) - if supplied_arg in disallowed: sys.exit( DISALLOWED_PIP_ARGS.format( - arg=supplied_arg, reason=DISALLOWED_ARGS[disallowed] + arg=supplied_arg, reason=DISALLOWED_ARGS[disallowed] ) ) - if not quiet: + + if verbose: click.secho("with args : \n\toutput file : '{}', \n\tentry point : '{}', \ \n\tpython : '{}', \n\tcompressed : {}" .format(output_file, entry_point or '', python or sys.executable, compressed)) @@ -181,17 +175,12 @@ def main( with TemporaryDirectory() as working_path: tmp_site_packages = Path(working_path, "site-packages") - if not quiet: - click.secho("Pip installing dependencies to {}...".format(site_packages), bold=True) - - # install deps into staged site-packages - pip.install( - ["--target", str(site_packages)] + list(pip_args), - ) if site_packages: shutil.copytree(site_packages, tmp_site_packages) if pip_args: + if verbose: + click.secho("Pip installing dependencies to {}...".format(site_packages), fg="green", bold=True) # install deps into staged site-packages pip.install(["--target", str(tmp_site_packages)] + list(pip_args)) @@ -199,12 +188,11 @@ def main( if entry_point is None and console_script is not None: try: entry_point = find_entry_point(site_packages, console_script) - if not quiet: + if verbose: click.secho("Discovered entry point '{}'".format(entry_point)) except KeyError: - sys.exit(crayons.red(NO_ENTRY_POINT.format(entry_point=console_script))) + sys.exit( NO_ENTRY_POINT.format(entry_point=console_script)) - entry_point = find_entry_point(tmp_site_packages, console_script) except KeyError: if not Path(tmp_site_packages, "bin", console_script).exists(): @@ -225,33 +213,16 @@ def main( bootstrap_target = Path(working_path, "_bootstrap") bootstrap_target.mkdir(parents=True, exist_ok=True) - if not quiet: + if verbose: click.secho("Injecting bootstrap code") + # copy bootstrap code copy_bootstrap(bootstrap_target) - if not quiet: + if verbose: click.secho("Creating zip archive") - with spinner(): - # create the zip - builder.create_archive( - Path(working_path), - target=Path(output_file), - interpreter=python or sys.executable, - main="_bootstrap:bootstrap", - compressed=compressed, - ) - - if not quiet: - conf_message = "Done, wrote output file to '{}'".format(output_file) - if entry_point: - conf_message += ", entry point is '{}'".format(entry_point) - else: - conf_message += ", no entry point specified." - click.secho(conf_message, bold=True) - - # create the zip + # create the zip builder.create_archive( Path(working_path), target=Path(output_file).expanduser(), @@ -260,5 +231,13 @@ def main( compressed=compressed, ) + if verbose: + conf_message = "Done, wrote output file to '{}'".format(output_file) + if entry_point: + conf_message += ", entry point is '{}'".format(entry_point) + else: + conf_message += ", no entry point specified." + click.secho(conf_message, bold=True) + if __name__ == "__main__": main() # pragma: no cover diff --git a/src/shiv/pip.py b/src/shiv/pip.py index 09d3170..59ca882 100644 --- a/src/shiv/pip.py +++ b/src/shiv/pip.py @@ -2,17 +2,13 @@ import os import subprocess import sys - import click -import crayons -from typing import Generator, List -import click +from typing import Generator, List from .bootstrap import _first_sitedir_index, _extend_python_path from .constants import PIP_REQUIRE_VIRTUALENV, PIP_INSTALL_ERROR - @contextlib.contextmanager def clean_pip_env() -> Generator[None, None, None]: """A context manager for temporarily removing 'PIP_REQUIRE_VIRTUALENV' from the environment. @@ -63,10 +59,7 @@ def install(args: List[str]) -> None: for output in process.stdout: if output: - - click.echo(crayons.blue(output.decode().rstrip())) click.echo(output.decode().rstrip()) - if process.wait() > 0: - sys.exit(crayons.red(PIP_INSTALL_ERROR)) + sys.exit(PIP_INSTALL_ERROR) From 280aba0b35a0089dd7cd040d23cf5d071b1c5a98 Mon Sep 17 00:00:00 2001 From: Ian MacLean Date: Wed, 8 May 2019 08:11:29 +0900 Subject: [PATCH 5/8] Fixed MyPy error. --- src/shiv/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shiv/cli.py b/src/shiv/cli.py index fde6329..782854a 100644 --- a/src/shiv/cli.py +++ b/src/shiv/cli.py @@ -172,6 +172,7 @@ def main( \n\tpython : '{}', \n\tcompressed : {}" .format(output_file, entry_point or '', python or sys.executable, compressed)) click.secho("\tpip args '{}' ".format(' '.join(pip_args))) + with TemporaryDirectory() as working_path: tmp_site_packages = Path(working_path, "site-packages") @@ -187,7 +188,7 @@ def main( # if entry_point is a console script, get the callable if entry_point is None and console_script is not None: try: - entry_point = find_entry_point(site_packages, console_script) + entry_point = find_entry_point(tmp_site_packages, console_script) if verbose: click.secho("Discovered entry point '{}'".format(entry_point)) except KeyError: From 271044fd067c721b9473b1b0e4d5795bc65ab2f6 Mon Sep 17 00:00:00 2001 From: Ian MacLean Date: Thu, 9 May 2019 08:25:14 +0900 Subject: [PATCH 6/8] flake8 formatting fixes --- src/shiv/cli.py | 16 +++++++--------- src/shiv/pip.py | 1 + 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/shiv/cli.py b/src/shiv/cli.py index 782854a..a5c5682 100644 --- a/src/shiv/cli.py +++ b/src/shiv/cli.py @@ -149,8 +149,7 @@ def main( """ if not pip_args and not site_packages: sys.exit(NO_PIP_ARGS_OR_SITE_PACKAGES) - - #verbose = "-v" in pip_args or '--verbose' in pip_args + if verbose: click.secho("shiv! ", bold=True) @@ -163,16 +162,15 @@ def main( if supplied_arg in disallowed: sys.exit( DISALLOWED_PIP_ARGS.format( - arg=supplied_arg, reason=DISALLOWED_ARGS[disallowed] + arg=supplied_arg, reason=DISALLOWED_ARGS[disallowed] ) ) - if verbose: click.secho("with args : \n\toutput file : '{}', \n\tentry point : '{}', \ \n\tpython : '{}', \n\tcompressed : {}" .format(output_file, entry_point or '', python or sys.executable, compressed)) click.secho("\tpip args '{}' ".format(' '.join(pip_args))) - + with TemporaryDirectory() as working_path: tmp_site_packages = Path(working_path, "site-packages") @@ -192,8 +190,7 @@ def main( if verbose: click.secho("Discovered entry point '{}'".format(entry_point)) except KeyError: - sys.exit( NO_ENTRY_POINT.format(entry_point=console_script)) - + sys.exit(NO_ENTRY_POINT.format(entry_point=console_script)) except KeyError: if not Path(tmp_site_packages, "bin", console_script).exists(): @@ -218,14 +215,14 @@ def main( if verbose: click.secho("Injecting bootstrap code") - + # copy bootstrap code copy_bootstrap(bootstrap_target) if verbose: click.secho("Creating zip archive") - # create the zip + # create the zip builder.create_archive( Path(working_path), target=Path(output_file).expanduser(), @@ -242,5 +239,6 @@ def main( conf_message += ", no entry point specified." click.secho(conf_message, bold=True) + if __name__ == "__main__": main() # pragma: no cover diff --git a/src/shiv/pip.py b/src/shiv/pip.py index f9e3511..778d736 100644 --- a/src/shiv/pip.py +++ b/src/shiv/pip.py @@ -9,6 +9,7 @@ from .bootstrap import _first_sitedir_index, _extend_python_path from .constants import PIP_REQUIRE_VIRTUALENV, PIP_INSTALL_ERROR + @contextlib.contextmanager def clean_pip_env() -> Generator[None, None, None]: """A context manager for temporarily removing 'PIP_REQUIRE_VIRTUALENV' from the environment. From 2f50bf75a20bb06bf86d2a26e656e03a56622ffd Mon Sep 17 00:00:00 2001 From: Ian MacLean Date: Sat, 11 May 2019 16:08:15 +0900 Subject: [PATCH 7/8] Cleaned up output and moved to f strings. --- setup.cfg | 2 +- src/shiv/cli.py | 44 +++++++++++++++++++++++++------------------- src/shiv/info.py | 16 +++++++++++----- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/setup.cfg b/setup.cfg index d2ebbe5..e86c52f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,7 +5,7 @@ tag = True [flake8] max-line-length = 160 -max-complexity = 15 +max-complexity = 18 exclude = docs test/package/setup.py [tool:pytest] diff --git a/src/shiv/cli.py b/src/shiv/cli.py index a5c5682..c2ceb9d 100644 --- a/src/shiv/cli.py +++ b/src/shiv/cli.py @@ -16,6 +16,7 @@ import click from . import pip +from .info import write_info from . import builder from . import bootstrap from .bootstrap.environment import Environment @@ -94,6 +95,13 @@ def _interpreter_path(append_version: bool = False) -> str: return sys.executable +def write_completed(output_file: str, entry_point: str = None): + """ Echo a completed summary """ + + click.secho(f"Done, create pyz with settings : ", fg="green", bold=True, nl=False) + write_info(False, pyz=output_file) + + @click.command( context_settings=dict( help_option_names=["-h", "--help", "--halp"], ignore_unknown_options=True @@ -117,7 +125,7 @@ def _interpreter_path(append_version: bool = False) -> str: help="Whether or not to compress your zip.", ) @click.option( - "--verbose/--quiet", + "--verbose/--quiet", "-v/-q", default=False, help="Whether or not to generate versose output.", ) @@ -150,9 +158,6 @@ def main( if not pip_args and not site_packages: sys.exit(NO_PIP_ARGS_OR_SITE_PACKAGES) - if verbose: - click.secho("shiv! ", bold=True) - if output_file is None: sys.exit(NO_OUTFILE) @@ -166,10 +171,18 @@ def main( ) ) if verbose: - click.secho("with args : \n\toutput file : '{}', \n\tentry point : '{}', \ - \n\tpython : '{}', \n\tcompressed : {}" - .format(output_file, entry_point or '', python or sys.executable, compressed)) - click.secho("\tpip args '{}' ".format(' '.join(pip_args))) + click.secho("Running Shiv with args : \n", fg="green", bold=True, nl=False) + click.secho("output_file: ", fg="blue", bold=True, nl=False) + click.secho(f"{output_file}", fg="white") + click.secho("entry_point: ", fg="blue", bold=True, nl=False) + click.secho(f"{entry_point or 'None'}", fg="white") + click.secho("python: ", fg="blue", bold=True, nl=False) + click.secho(f"{python or sys.executable}", fg="white") + click.secho("compressed: ", fg="blue", bold=True, nl=False) + click.secho(f"{compressed}", fg="white") + click.secho("pip args: ", fg="blue", bold=True, nl=False) + click.secho(f"{' '.join(pip_args)}") # ' '.join(pip_args) + click.echo() with TemporaryDirectory() as working_path: tmp_site_packages = Path(working_path, "site-packages") @@ -179,18 +192,16 @@ def main( if pip_args: if verbose: - click.secho("Pip installing dependencies to {}...".format(site_packages), fg="green", bold=True) + click.secho(f"Pip installing dependencies to {site_packages}...", fg="green", bold=True, nl=False) # install deps into staged site-packages pip.install(["--target", str(tmp_site_packages)] + list(pip_args)) - + click.secho() # if entry_point is a console script, get the callable if entry_point is None and console_script is not None: try: entry_point = find_entry_point(tmp_site_packages, console_script) if verbose: - click.secho("Discovered entry point '{}'".format(entry_point)) - except KeyError: - sys.exit(NO_ENTRY_POINT.format(entry_point=console_script)) + click.secho(f"Discovered entry point '{entry_point}'") except KeyError: if not Path(tmp_site_packages, "bin", console_script).exists(): @@ -232,12 +243,7 @@ def main( ) if verbose: - conf_message = "Done, wrote output file to '{}'".format(output_file) - if entry_point: - conf_message += ", entry point is '{}'".format(entry_point) - else: - conf_message += ", no entry point specified." - click.secho(conf_message, bold=True) + write_completed(output_file, entry_point) if __name__ == "__main__": diff --git a/src/shiv/info.py b/src/shiv/info.py index 71bea8a..79e7e0d 100644 --- a/src/shiv/info.py +++ b/src/shiv/info.py @@ -3,11 +3,8 @@ import zipfile -@click.command(context_settings=dict(help_option_names=["-h", "--help", "--halp"])) -@click.option("--json", "-j", "print_as_json", is_flag=True, help="output as plain json") -@click.argument("pyz") -def main(print_as_json, pyz): - """A simple utility to print debugging information about PYZ files created with ``shiv``""" +def write_info(print_as_json: bool, pyz: str): + """print debugging information about the PYZ file passed in """ zip_file = zipfile.ZipFile(pyz) data = json.loads(zip_file.read("environment.json")) @@ -26,3 +23,12 @@ def main(print_as_json, pyz): click.secho(f"{value}", fg="white") click.echo() + + +@click.command(context_settings=dict(help_option_names=["-h", "--help", "--halp"])) +@click.option("--json", "-j", "print_as_json", is_flag=True, help="output as plain json") +@click.argument("pyz") +def main(print_as_json, pyz): + """A simple utility to print debugging information about PYZ files created with ``shiv``""" + + write_info(print_as_json, pyz) From 70e99ce2778506646752d89f07a68cd824d183ee Mon Sep 17 00:00:00 2001 From: Ian MacLean Date: Sun, 12 May 2019 14:39:12 +0900 Subject: [PATCH 8/8] minor cleanups post merge. --- setup.py | 2 -- src/shiv/cli.py | 4 ++-- src/shiv/pip.py | 3 ++- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/setup.py b/setup.py index c08e1c8..4100faf 100644 --- a/setup.py +++ b/setup.py @@ -12,12 +12,10 @@ from pathlib import Path from setuptools.command import easy_install - install_requires = [ 'click>=6.7,!=7.0', 'pip>=9.0.3', 'setuptools', - ] extras_require = { diff --git a/src/shiv/cli.py b/src/shiv/cli.py index acfb748..eec0e3a 100644 --- a/src/shiv/cli.py +++ b/src/shiv/cli.py @@ -181,7 +181,7 @@ def main( click.secho("compressed: ", fg="blue", bold=True, nl=False) click.secho(f"{compressed}", fg="white") click.secho("pip args: ", fg="blue", bold=True, nl=False) - click.secho(f"{' '.join(pip_args)}") # ' '.join(pip_args) + click.secho(f"{' '.join(pip_args)}") click.echo() with TemporaryDirectory() as working_path: @@ -195,7 +195,7 @@ def main( click.secho(f"Pip installing dependencies to {site_packages}...", fg="green", bold=True, nl=False) # install deps into staged site-packages pip.install(["--target", str(tmp_site_packages)] + list(pip_args)) - click.secho() + click.secho("") # if entry_point is a console script, get the callable if entry_point is None and console_script is not None: try: diff --git a/src/shiv/pip.py b/src/shiv/pip.py index 778d736..d2b4a8f 100644 --- a/src/shiv/pip.py +++ b/src/shiv/pip.py @@ -2,10 +2,11 @@ import os import subprocess import sys -import click from typing import Generator, List +import click + from .bootstrap import _first_sitedir_index, _extend_python_path from .constants import PIP_REQUIRE_VIRTUALENV, PIP_INSTALL_ERROR