Skip to content

Commit e818ca5

Browse files
committed
Fix double completion message on locking
- Pass `pre` correctly when using `pipenv install --pre` - Ensures we always make inline tables when writing to pipfile - Fixes #3183 - Fixes #3185 Signed-off-by: Dan Ryan <[email protected]>
1 parent a167885 commit e818ca5

File tree

6 files changed

+85
-59
lines changed

6 files changed

+85
-59
lines changed

news/3183.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed new spinner success message to write only one success message during resolution.

news/3185.bugfix.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Pipenv will now correctly respect the ``--pre`` option when used with ``pipenv install``.

pipenv/cli/options.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ def common_options(f):
338338
def install_base_options(f):
339339
f = common_options(f)
340340
f = dev_option(f)
341+
f = pre_option(f)
341342
f = keep_outdated_option(f)
342343
return f
343344

@@ -353,7 +354,6 @@ def uninstall_options(f):
353354
def lock_options(f):
354355
f = install_base_options(f)
355356
f = requirements_flag(f)
356-
f = pre_option(f)
357357
return f
358358

359359

pipenv/core.py

+11-19
Original file line numberDiff line numberDiff line change
@@ -1028,23 +1028,6 @@ def do_lock(
10281028
deps = convert_deps_to_pip(
10291029
settings["packages"], project, r=False, include_index=True
10301030
)
1031-
results = venv_resolve_deps(
1032-
deps,
1033-
which=which,
1034-
project=project,
1035-
clear=clear,
1036-
pre=pre,
1037-
allow_global=system,
1038-
pypi_mirror=pypi_mirror,
1039-
)
1040-
# Add dependencies to lockfile.
1041-
for dep in results:
1042-
is_top_level = dep["name"] in settings["packages"]
1043-
pipfile_entry = settings["packages"][dep["name"]] if is_top_level else None
1044-
dep_lockfile = clean_resolved_dep(
1045-
dep, is_top_level=is_top_level, pipfile_entry=pipfile_entry
1046-
)
1047-
lockfile[settings["lockfile_key"]].update(dep_lockfile)
10481031
# Add refs for VCS installs.
10491032
# TODO: be smarter about this.
10501033
vcs_reqs, vcs_lockfile = get_vcs_deps(
@@ -1056,15 +1039,24 @@ def do_lock(
10561039
dev=settings["dev"],
10571040
)
10581041
vcs_lines = [req.as_line() for req in vcs_reqs if req.editable]
1059-
vcs_results = venv_resolve_deps(
1060-
vcs_lines,
1042+
results, vcs_results = venv_resolve_deps(
1043+
deps,
10611044
which=which,
10621045
project=project,
1046+
vcs_deps=vcs_lines,
10631047
clear=clear,
10641048
pre=pre,
10651049
allow_global=system,
10661050
pypi_mirror=pypi_mirror,
10671051
)
1052+
# Add dependencies to lockfile.
1053+
for dep in results:
1054+
is_top_level = dep["name"] in settings["packages"]
1055+
pipfile_entry = settings["packages"][dep["name"]] if is_top_level else None
1056+
dep_lockfile = clean_resolved_dep(
1057+
dep, is_top_level=is_top_level, pipfile_entry=pipfile_entry
1058+
)
1059+
lockfile[settings["lockfile_key"]].update(dep_lockfile)
10681060
for dep in vcs_results:
10691061
normalized = pep423_name(dep["name"])
10701062
if not hasattr(dep, "keys") or not hasattr(dep["name"], "keys"):

pipenv/project.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -617,15 +617,14 @@ def _parse_pipfile(self, contents):
617617
data = tomlkit.parse(contents)
618618
# Convert all outline tables to inline tables.
619619
for section in ("packages", "dev-packages"):
620-
table_data = data.get(section, tomlkit.table())
620+
table_data = data.get(section, {})
621621
for package, value in table_data.items():
622622
if isinstance(value, dict):
623-
table = tomlkit.inline_table()
624-
table.update(value)
625-
table_data[package] = table
623+
package_table = tomlkit.inline_table()
624+
package_table.update(value)
625+
data[section][package] = package_table
626626
else:
627-
table_data[package] = value
628-
data[section] = table_data
627+
data[section][package] = value
629628
return data
630629
except Exception:
631630
# We lose comments here, but it's for the best.)
@@ -1036,6 +1035,10 @@ def add_package_to_pipfile(self, package, dev=False):
10361035
# Skip for wildcard version
10371036
return
10381037
# Add the package to the group.
1038+
if isinstance(converted, dict):
1039+
package_table = tomlkit.inline_table()
1040+
package_table.update(converted)
1041+
converted = package_table
10391042
p[key][name or package.normalized_name] = converted
10401043
# Write Pipfile.
10411044
self.write_toml(p)

pipenv/utils.py

+62-33
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,37 @@ def create_spinner(text, nospin=None, spinner_name=None):
468468
yield sp
469469

470470

471+
def resolve(cmd, sp):
472+
from .vendor import delegator
473+
from .cmdparse import Script
474+
from .vendor.pexpect.exceptions import EOF, TIMEOUT
475+
from .vendor.vistir.compat import to_native_string
476+
EOF.__module__ = "pexpect.exceptions"
477+
from ._compat import decode_output
478+
c = delegator.run(Script.parse(cmd).cmdify(), block=False, env=os.environ.copy())
479+
_out = decode_output("")
480+
result = None
481+
out = to_native_string("")
482+
while True:
483+
try:
484+
result = c.expect(u"\n", timeout=environments.PIPENV_TIMEOUT)
485+
except (EOF, TIMEOUT):
486+
pass
487+
if result is None:
488+
break
489+
_out = c.subprocess.before
490+
if _out is not None:
491+
_out = decode_output("{0}".format(_out))
492+
out += _out
493+
sp.text = to_native_string("{0}".format(_out[:100]))
494+
if environments.is_verbose():
495+
if _out is not None:
496+
sp._hide_cursor()
497+
sp.write(_out.rstrip())
498+
sp._show_cursor()
499+
return c
500+
501+
471502
def venv_resolve_deps(
472503
deps,
473504
which,
@@ -476,19 +507,16 @@ def venv_resolve_deps(
476507
clear=False,
477508
allow_global=False,
478509
pypi_mirror=None,
510+
vcs_deps=None,
479511
):
480512
from .vendor.vistir.misc import fs_str
481-
from .vendor.vistir.compat import Path, to_native_string, JSONDecodeError
513+
from .vendor.vistir.compat import Path, JSONDecodeError
482514
from .vendor.vistir.path import create_tracked_tempdir
483-
from .cmdparse import Script
484-
from .vendor.pexpect.exceptions import EOF, TIMEOUT
485-
from .vendor import delegator
486515
from . import resolver
487-
from ._compat import decode_output
488516
import json
489517

490518
if not deps:
491-
return []
519+
return [], []
492520

493521
req_dir = create_tracked_tempdir(prefix="pipenv", suffix="requirements")
494522
cmd = [
@@ -509,29 +537,8 @@ def venv_resolve_deps(
509537
os.environ["PIPENV_VERBOSITY"] = str(environments.PIPENV_VERBOSITY)
510538
os.environ["PIPENV_REQ_DIR"] = fs_str(req_dir)
511539
os.environ["PIP_NO_INPUT"] = fs_str("1")
512-
out = to_native_string("")
513-
EOF.__module__ = "pexpect.exceptions"
514540
with create_spinner(text=fs_str("Locking...")) as sp:
515-
c = delegator.run(Script.parse(cmd).cmdify(), block=False, env=os.environ.copy())
516-
_out = decode_output("")
517-
result = None
518-
while True:
519-
try:
520-
result = c.expect(u"\n", timeout=environments.PIPENV_TIMEOUT)
521-
except (EOF, TIMEOUT):
522-
pass
523-
if result is None:
524-
break
525-
_out = c.subprocess.before
526-
if _out is not None:
527-
_out = decode_output("{0}".format(_out))
528-
out += _out
529-
sp.text = to_native_string("{0}".format(_out[:100]))
530-
if environments.is_verbose():
531-
if _out is not None:
532-
sp._hide_cursor()
533-
sp.write(_out.rstrip())
534-
sp._show_cursor()
541+
c = resolve(cmd, sp)
535542
c.block()
536543
if c.return_code != 0:
537544
sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(
@@ -540,17 +547,39 @@ def venv_resolve_deps(
540547
click_echo(c.out.strip(), err=True)
541548
click_echo(c.err.strip(), err=True)
542549
sys.exit(c.return_code)
550+
results = c.out
551+
if vcs_deps:
552+
with temp_environ():
553+
os.environ["PIPENV_PACKAGES"] = str("\n".join(vcs_deps))
554+
vcs_c = resolve(cmd, sp)
555+
c.block()
556+
if c.return_code != 0:
557+
sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format(
558+
"Locking Failed!"
559+
))
560+
click_echo(c.out.strip(), err=True)
561+
click_echo(c.err.strip(), err=True)
562+
sys.exit(c.return_code)
563+
vcs_results = vcs_c.out
564+
vcs_err = vcs_c.err
543565
else:
544-
sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
566+
vcs_results = ""
567+
vcs_err = ""
568+
sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!"))
569+
outputs = [results, vcs_results]
545570
if environments.is_verbose():
546-
click_echo(c.out.split("RESULTS:")[0], err=True)
571+
for output in outputs:
572+
click_echo(output.split("RESULTS:")[0], err=True)
547573
try:
548-
return json.loads(c.out.split("RESULTS:")[1].strip())
574+
results = json.loads(results.split("RESULTS:")[1].strip())
575+
vcs_results = json.loads(vcs_results.split("RESULTS:")[1].strip())
549576

550577
except (IndexError, JSONDecodeError):
551-
click_echo(c.out.strip(), err=True)
552-
click_echo(c.err.strip(), err=True)
578+
for out, err in [(c.out, c.err), (vcs_results, vcs_err)]:
579+
click_echo(out.strip(), err=True)
580+
click_echo(err.strip(), err=True)
553581
raise RuntimeError("There was a problem with locking.")
582+
return results, vcs_results
554583

555584

556585
def resolve_deps(

0 commit comments

Comments
 (0)