Skip to content

Commit f95b671

Browse files
authored
Merge pull request #5468 from pypa/remove-yaspin-spinner
Remove yaspin spinner
2 parents d7e3292 + baf1124 commit f95b671

File tree

18 files changed

+163
-556
lines changed

18 files changed

+163
-556
lines changed

news/5468.vendor.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* Replace yaspin spinner with rich spinner.
2+
* Bump vistir version to 0.7.4

pipenv/cli/command.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ def cli(
8080
site_packages=None,
8181
**kwargs,
8282
):
83+
from pipenv.patched.pip._vendor import rich
8384
from pipenv.utils.shell import system_which
84-
from pipenv.utils.spinner import create_spinner
8585

8686
load_dot_env(state.project, quiet=state.quiet)
8787

@@ -188,7 +188,10 @@ def cli(
188188
)
189189
)
190190
)
191-
with create_spinner(text="Running...", setting=state.project.s):
191+
192+
console = rich.console.Console()
193+
# TODO: add state.project.s to spinner status
194+
with console.status("Running..."):
192195
# Remove the virtualenv.
193196
cleanup_virtualenv(state.project, bare=True)
194197
return 0

pipenv/core.py

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
)
2525
from pipenv.patched.pip._internal.req.req_file import parse_requirements
2626
from pipenv.patched.pip._internal.utils.misc import split_auth_from_netloc
27+
from pipenv.patched.pip._vendor import rich
2728
from pipenv.patched.pip._vendor.packaging.utils import canonicalize_name
2829
from pipenv.project import Project
2930
from pipenv.utils.constants import MYPY_RUNNING
@@ -52,7 +53,6 @@
5253
subprocess_run,
5354
system_which,
5455
)
55-
from pipenv.utils.spinner import create_spinner
5656
from pipenv.vendor import click, plette, vistir
5757
from pipenv.vendor.requirementslib.models.requirements import Requirement
5858

@@ -94,6 +94,10 @@
9494
STARTING_LABEL = " "
9595

9696

97+
console = rich.console.Console()
98+
err = rich.console.Console(stderr=True)
99+
100+
97101
def do_clear(project):
98102
from pipenv.patched.pip._internal import locations
99103

@@ -245,14 +249,16 @@ def ensure_pipfile(project, validate=True, skip_requirements=False, system=False
245249
)
246250
# Create a Pipfile...
247251
project.create_pipfile(python=python)
248-
with create_spinner("Importing requirements...", project.s) as sp:
252+
with console.status(
253+
"Importing requirements...", spinner=project.s.PIPENV_SPINNER
254+
) as st:
249255
# Import requirements.txt.
250256
try:
251257
import_requirements(project)
252258
except Exception:
253-
sp.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format("Failed..."))
259+
err.print(environments.PIPENV_SPINNER_FAIL_TEXT.format("Failed..."))
254260
else:
255-
sp.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
261+
st.update(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
256262
# Warn the user of side-effects.
257263
click.echo(
258264
"{0}: Your {1} now contains pinned versions, if your {2} did. \n"
@@ -398,17 +404,18 @@ def abort(msg=""):
398404
click.style("...", bold=True),
399405
)
400406
)
401-
with create_spinner("Installing python...", project.s) as sp:
407+
# TOOD: pass project settings to console.status
408+
with console.status("Installing python...") as st:
402409
try:
403410
c = installer.install(version)
404411
except InstallerError as e:
405-
sp.fail(
412+
err.print(
406413
environments.PIPENV_SPINNER_FAIL_TEXT.format("Failed...")
407414
)
408415
click.echo(fix_utf8("Something went wrong..."), err=True)
409416
click.secho(e.err, fg="cyan", err=True)
410417
else:
411-
sp.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
418+
st(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
412419
# Print the results, in a beautiful blue...
413420
click.secho(c.stdout, fg="cyan", err=True)
414421
# Clear the pythonfinder caches
@@ -1003,20 +1010,22 @@ def do_create_virtualenv(project, python=None, site_packages=None, pypi_mirror=N
10031010

10041011
# Actually create the virtualenv.
10051012
error = None
1006-
with create_spinner("Creating virtual environment...", project.s) as sp:
1013+
with console.status(
1014+
"Creating virtual environment...", spinner=project.s.PIPENV_SPINNER
1015+
):
10071016
c = subprocess_run(cmd, env=pip_config)
10081017
click.secho(f"{c.stdout}", fg="cyan", err=True)
10091018
if c.returncode != 0:
10101019
error = (
10111020
c.stderr if project.s.is_verbose() else exceptions.prettify_exc(c.stderr)
10121021
)
1013-
sp.fail(
1022+
err.print(
10141023
environments.PIPENV_SPINNER_FAIL_TEXT.format(
10151024
"Failed creating virtual environment"
10161025
)
10171026
)
10181027
else:
1019-
sp.green.ok(
1028+
console.print(
10201029
environments.PIPENV_SPINNER_OK_TEXT.format(
10211030
"Successfully created virtual environment!"
10221031
)
@@ -2284,36 +2293,37 @@ def do_install(
22842293
extra_pip_args=extra_pip_args,
22852294
categories=categories,
22862295
)
2296+
22872297
for pkg_line in pkg_list:
22882298
click.secho(
22892299
fix_utf8(f"Installing {pkg_line}..."),
22902300
fg="green",
22912301
bold=True,
22922302
)
22932303
# pip install:
2294-
with vistir.contextmanagers.temp_environ(), create_spinner(
2295-
"Installing...", project.s
2296-
) as sp:
2304+
with vistir.contextmanagers.temp_environ(), console.status(
2305+
"Installing...", spinner=project.s.PIPENV_SPINNER
2306+
) as st:
22972307
if not system:
22982308
os.environ["PIP_USER"] = "0"
22992309
if "PYTHONHOME" in os.environ:
23002310
del os.environ["PYTHONHOME"]
2301-
sp.text = f"Resolving {pkg_line}..."
2311+
st.update(f"Resolving {pkg_line}...")
23022312
try:
23032313
pkg_requirement = Requirement.from_line(pkg_line)
23042314
except ValueError as e:
2305-
sp.write_err("{}: {}".format(click.style("WARNING", fg="red"), e))
2306-
sp.red.fail(
2315+
err.print("{}: {}".format(click.style("WARNING", fg="red"), e))
2316+
err.print(
23072317
environments.PIPENV_SPINNER_FAIL_TEXT.format(
23082318
"Installation Failed"
23092319
)
23102320
)
23112321
sys.exit(1)
2312-
sp.text = "Installing..."
2322+
st.update("Installing...")
23132323
try:
2314-
sp.text = f"Installing {pkg_requirement.name}..."
2324+
st.update(f"Installing {pkg_requirement.name}...")
23152325
if project.s.is_verbose():
2316-
sp.hide_and_write(
2326+
st.update(
23172327
f"Installing package: {pkg_requirement.as_line(include_hashes=False)}"
23182328
)
23192329
c = pip_install(
@@ -2332,34 +2342,32 @@ def do_install(
23322342
extra_pip_args=extra_pip_args,
23332343
)
23342344
if c.returncode:
2335-
sp.write_err(
2345+
err.print(
23362346
"{} An error occurred while installing {}!".format(
23372347
click.style("Error: ", fg="red", bold=True),
23382348
click.style(pkg_line, fg="green"),
23392349
),
23402350
)
2341-
sp.write_err(f"Error text: {c.stdout}")
2342-
sp.write_err(click.style(format_pip_error(c.stderr), fg="cyan"))
2351+
err.print(f"Error text: {c.stdout}")
2352+
err.print(click.style(format_pip_error(c.stderr), fg="cyan"))
23432353
if project.s.is_verbose():
2344-
sp.write_err(
2345-
click.style(format_pip_output(c.stdout), fg="cyan")
2346-
)
2354+
err.print(click.style(format_pip_output(c.stdout), fg="cyan"))
23472355
if "setup.py egg_info" in c.stderr:
2348-
sp.write_err(
2356+
err.print(
23492357
"This is likely caused by a bug in {}. "
23502358
"Report this to its maintainers.".format(
23512359
click.style(pkg_requirement.name, fg="green")
23522360
)
23532361
)
2354-
sp.red.fail(
2362+
err.print(
23552363
environments.PIPENV_SPINNER_FAIL_TEXT.format(
23562364
"Installation Failed"
23572365
)
23582366
)
23592367
sys.exit(1)
23602368
except (ValueError, RuntimeError) as e:
2361-
sp.write_err("{}: {}".format(click.style("WARNING", fg="red"), e))
2362-
sp.red.fail(
2369+
err.print("{}: {}".format(click.style("WARNING", fg="red"), e))
2370+
err.print(
23632371
environments.PIPENV_SPINNER_FAIL_TEXT.format(
23642372
"Installation Failed",
23652373
)
@@ -2371,7 +2379,7 @@ def do_install(
23712379
and not pkg_requirement.editable
23722380
and not project.s.PIPENV_RESOLVE_VCS
23732381
):
2374-
sp.write_err(
2382+
err.print(
23752383
"{}: You installed a VCS dependency in non-editable mode. "
23762384
"This will work fine, but sub-dependencies will not be resolved by {}."
23772385
"\n To enable this sub-dependency functionality, specify that this dependency is editable."
@@ -2388,7 +2396,7 @@ def do_install(
23882396
pipfile_sections = "[dev-packages]"
23892397
else:
23902398
pipfile_sections = "[packages]"
2391-
sp.write(
2399+
st.update(
23922400
"{} {} {} {}{}".format(
23932401
click.style("Adding", bold=True),
23942402
click.style(f"{pkg_requirement.name}", fg="green", bold=True),
@@ -2416,18 +2424,19 @@ def do_install(
24162424
except ValueError:
24172425
import traceback
24182426

2419-
sp.write_err(
2427+
err.print(
24202428
"{} {}".format(
24212429
click.style("Error:", fg="red", bold=True),
24222430
traceback.format_exc(),
24232431
)
24242432
)
2425-
sp.fail(
2433+
err.print(
24262434
environments.PIPENV_SPINNER_FAIL_TEXT.format(
24272435
"Failed adding package to Pipfile"
24282436
)
24292437
)
2430-
sp.ok(
2438+
# ok has a nice v in front, should do something similir with rich
2439+
st.update(
24312440
environments.PIPENV_SPINNER_OK_TEXT.format("Installation Succeeded")
24322441
)
24332442
# Update project settings with pre preference.

pipenv/environments.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,21 @@ def __init__(self) -> None:
218218
if PIPENV_IS_CI:
219219
self.PIPENV_NOSPIN = True
220220

221-
pipenv_spinner = "dots" if not os.name == "nt" else "bouncingBar"
222-
self.PIPENV_SPINNER = get_from_env(
223-
"SPINNER", check_for_negation=False, default=pipenv_spinner
224-
)
221+
if self.PIPENV_NOSPIN:
222+
from pipenv.patched.pip._vendor.rich import _spinners
223+
224+
_spinners.SPINNERS[None] = {"interval": 80, "frames": " "}
225+
self.PIPENV_SPINNER = None
226+
else:
227+
pipenv_spinner = "dots" if not os.name == "nt" else "bouncingBar"
228+
self.PIPENV_SPINNER = get_from_env(
229+
"SPINNER", check_for_negation=False, default=pipenv_spinner
230+
)
225231
"""Sets the default spinner type.
226232
227-
Spinners are identical to the ``node.js`` spinners and can be found at
228-
https://github.com/sindresorhus/cli-spinners
233+
You can see which spinners are available by running::
234+
235+
$ python -m pipenv.patched.pip._vendor.rich.spinner
229236
"""
230237

231238
pipenv_pipfile = get_from_env("PIPFILE", check_for_negation=False)

pipenv/utils/resolver.py

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from typing import Dict, List, Optional, Set, Tuple, Union
1212

1313
from pipenv import environments
14-
from pipenv._compat import decode_for_output
1514
from pipenv.exceptions import RequirementError, ResolutionFailure
1615
from pipenv.patched.pip._internal.cache import WheelCache
1716
from pipenv.patched.pip._internal.commands.install import InstallCommand
@@ -27,7 +26,7 @@
2726
from pipenv.patched.pip._internal.req.req_file import parse_requirements
2827
from pipenv.patched.pip._internal.utils.hashes import FAVORITE_HASH
2928
from pipenv.patched.pip._internal.utils.temp_dir import global_tempdir_manager
30-
from pipenv.patched.pip._vendor import pkg_resources
29+
from pipenv.patched.pip._vendor import pkg_resources, rich
3130
from pipenv.project import Project
3231
from pipenv.vendor import click
3332
from pipenv.vendor.requirementslib import Requirement
@@ -59,7 +58,9 @@
5958
from .internet import _get_requests_session, is_pypi_url
6059
from .locking import format_requirement_for_lockfile, prepare_lockfile
6160
from .shell import make_posix, subprocess_run, temp_environ
62-
from .spinner import create_spinner
61+
62+
console = rich.console.Console()
63+
err = rich.console.Console(stderr=True)
6364

6465

6566
def get_package_finder(
@@ -911,7 +912,7 @@ def actually_resolve_deps(
911912
return (results, hashes, resolver.markers_lookup, resolver, resolver.skipped)
912913

913914

914-
def resolve(cmd, sp, project):
915+
def resolve(cmd, st, project):
915916
from pipenv._compat import decode_output
916917
from pipenv.cmdparse import Script
917918
from pipenv.vendor.vistir.misc import echo
@@ -925,13 +926,13 @@ def resolve(cmd, sp, project):
925926
continue
926927
err += line
927928
if is_verbose:
928-
sp.hide_and_write(line.rstrip())
929+
st.update(line.rstrip())
929930

930931
c.wait()
931932
returncode = c.poll()
932933
out = c.stdout.read()
933934
if returncode != 0:
934-
sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format("Locking Failed!"))
935+
st.update(environments.PIPENV_SPINNER_FAIL_TEXT.format("Locking Failed!"))
935936
echo(out.strip(), err=True)
936937
if not is_verbose:
937938
echo(err, err=True)
@@ -1026,14 +1027,12 @@ def venv_resolve_deps(
10261027
os.environ.pop("PIPENV_SITE_DIR", None)
10271028
if keep_outdated:
10281029
os.environ["PIPENV_KEEP_OUTDATED"] = "1"
1029-
with create_spinner(
1030-
text=decode_for_output("Locking..."), setting=project.s
1031-
) as sp:
1030+
with console.status("Locking...", spinner=project.s.PIPENV_SPINNER) as st:
10321031
# This conversion is somewhat slow on local and file-type requirements since
10331032
# we now download those requirements / make temporary folders to perform
10341033
# dependency resolution on them, so we are including this step inside the
10351034
# spinner context manager for the UX improvement
1036-
sp.write(decode_for_output("Building requirements..."))
1035+
st.update("Building requirements...")
10371036
deps = convert_deps_to_pip(deps, project, include_index=True)
10381037
constraints = set(deps)
10391038
with tempfile.NamedTemporaryFile(
@@ -1042,16 +1041,14 @@ def venv_resolve_deps(
10421041
constraints_file.write(str("\n".join(constraints)))
10431042
cmd.append("--constraints-file")
10441043
cmd.append(constraints_file.name)
1045-
sp.write(decode_for_output("Resolving dependencies..."))
1046-
c = resolve(cmd, sp, project=project)
1044+
st.update("Resolving dependencies...")
1045+
c = resolve(cmd, st, project=project)
10471046
if c.returncode == 0:
1048-
sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
1047+
st.update(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
10491048
if not project.s.is_verbose() and c.stderr.strip():
10501049
click.echo(click.style(f"Warning: {c.stderr.strip()}"), err=True)
10511050
else:
1052-
sp.red.fail(
1053-
environments.PIPENV_SPINNER_FAIL_TEXT.format("Locking Failed!")
1054-
)
1051+
st.update(environments.PIPENV_SPINNER_FAIL_TEXT.format("Locking Failed!"))
10551052
click.echo(f"Output: {c.stdout.strip()}", err=True)
10561053
click.echo(f"Error: {c.stderr.strip()}", err=True)
10571054
try:

pipenv/utils/spinner.py

Lines changed: 0 additions & 18 deletions
This file was deleted.

pipenv/vendor/vendor.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ shellingham==1.5.0
1919
termcolor==1.1.0
2020
toml==0.10.2
2121
tomlkit==0.9.2
22-
vistir==0.6.1
22+
vistir==0.7.4
2323
wheel==0.37.1
2424
yaspin==2.0.0

0 commit comments

Comments
 (0)