From e818ca5af63d7480f51385b4dd3c28dab197b643 Mon Sep 17 00:00:00 2001 From: Dan Ryan Date: Wed, 7 Nov 2018 19:26:38 -0500 Subject: [PATCH] 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 --- news/3183.bugfix.rst | 1 + news/3185.bugfix.rst | 1 + pipenv/cli/options.py | 2 +- pipenv/core.py | 34 ++++++---------- pipenv/project.py | 15 ++++--- pipenv/utils.py | 95 ++++++++++++++++++++++++++++--------------- 6 files changed, 87 insertions(+), 61 deletions(-) create mode 100644 news/3183.bugfix.rst create mode 100644 news/3185.bugfix.rst diff --git a/news/3183.bugfix.rst b/news/3183.bugfix.rst new file mode 100644 index 00000000..19e1d54a --- /dev/null +++ b/news/3183.bugfix.rst @@ -0,0 +1 @@ +Fixed new spinner success message to write only one success message during resolution. diff --git a/news/3185.bugfix.rst b/news/3185.bugfix.rst new file mode 100644 index 00000000..b6ffee2b --- /dev/null +++ b/news/3185.bugfix.rst @@ -0,0 +1 @@ +Pipenv will now correctly respect the ``--pre`` option when used with ``pipenv install``. diff --git a/pipenv/cli/options.py b/pipenv/cli/options.py index 3a361c5e..208c0c66 100644 --- a/pipenv/cli/options.py +++ b/pipenv/cli/options.py @@ -338,6 +338,7 @@ def common_options(f): def install_base_options(f): f = common_options(f) f = dev_option(f) + f = pre_option(f) f = keep_outdated_option(f) return f @@ -353,7 +354,6 @@ def uninstall_options(f): def lock_options(f): f = install_base_options(f) f = requirements_flag(f) - f = pre_option(f) return f diff --git a/pipenv/core.py b/pipenv/core.py index 758ef3fa..4a292139 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -1028,10 +1028,22 @@ def do_lock( deps = convert_deps_to_pip( settings["packages"], project, r=False, include_index=True ) - results = venv_resolve_deps( + # Add refs for VCS installs. + # TODO: be smarter about this. + vcs_reqs, vcs_lockfile = get_vcs_deps( + project, + which=which, + clear=clear, + pre=pre, + allow_global=system, + dev=settings["dev"], + ) + vcs_lines = [req.as_line() for req in vcs_reqs if req.editable] + results, vcs_results = venv_resolve_deps( deps, which=which, project=project, + vcs_deps=vcs_lines, clear=clear, pre=pre, allow_global=system, @@ -1045,26 +1057,6 @@ def do_lock( dep, is_top_level=is_top_level, pipfile_entry=pipfile_entry ) lockfile[settings["lockfile_key"]].update(dep_lockfile) - # Add refs for VCS installs. - # TODO: be smarter about this. - vcs_reqs, vcs_lockfile = get_vcs_deps( - project, - which=which, - clear=clear, - pre=pre, - allow_global=system, - dev=settings["dev"], - ) - vcs_lines = [req.as_line() for req in vcs_reqs if req.editable] - vcs_results = venv_resolve_deps( - vcs_lines, - which=which, - project=project, - clear=clear, - pre=pre, - allow_global=system, - pypi_mirror=pypi_mirror, - ) for dep in vcs_results: normalized = pep423_name(dep["name"]) if not hasattr(dep, "keys") or not hasattr(dep["name"], "keys"): diff --git a/pipenv/project.py b/pipenv/project.py index 26b4cf0c..98824d94 100644 --- a/pipenv/project.py +++ b/pipenv/project.py @@ -617,15 +617,14 @@ class Project(object): data = tomlkit.parse(contents) # Convert all outline tables to inline tables. for section in ("packages", "dev-packages"): - table_data = data.get(section, tomlkit.table()) + table_data = data.get(section, {}) for package, value in table_data.items(): if isinstance(value, dict): - table = tomlkit.inline_table() - table.update(value) - table_data[package] = table + package_table = tomlkit.inline_table() + package_table.update(value) + data[section][package] = package_table else: - table_data[package] = value - data[section] = table_data + data[section][package] = value return data except Exception: # We lose comments here, but it's for the best.) @@ -1036,6 +1035,10 @@ class Project(object): # Skip for wildcard version return # Add the package to the group. + if isinstance(converted, dict): + package_table = tomlkit.inline_table() + package_table.update(converted) + converted = package_table p[key][name or package.normalized_name] = converted # Write Pipfile. self.write_toml(p) diff --git a/pipenv/utils.py b/pipenv/utils.py index c9feeafd..26268ab2 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -468,6 +468,37 @@ def create_spinner(text, nospin=None, spinner_name=None): yield sp +def resolve(cmd, sp): + from .vendor import delegator + from .cmdparse import Script + from .vendor.pexpect.exceptions import EOF, TIMEOUT + from .vendor.vistir.compat import to_native_string + EOF.__module__ = "pexpect.exceptions" + from ._compat import decode_output + c = delegator.run(Script.parse(cmd).cmdify(), block=False, env=os.environ.copy()) + _out = decode_output("") + result = None + out = to_native_string("") + while True: + try: + result = c.expect(u"\n", timeout=environments.PIPENV_TIMEOUT) + except (EOF, TIMEOUT): + pass + if result is None: + break + _out = c.subprocess.before + if _out is not None: + _out = decode_output("{0}".format(_out)) + out += _out + sp.text = to_native_string("{0}".format(_out[:100])) + if environments.is_verbose(): + if _out is not None: + sp._hide_cursor() + sp.write(_out.rstrip()) + sp._show_cursor() + return c + + def venv_resolve_deps( deps, which, @@ -476,19 +507,16 @@ def venv_resolve_deps( clear=False, allow_global=False, pypi_mirror=None, + vcs_deps=None, ): from .vendor.vistir.misc import fs_str - from .vendor.vistir.compat import Path, to_native_string, JSONDecodeError + from .vendor.vistir.compat import Path, JSONDecodeError from .vendor.vistir.path import create_tracked_tempdir - from .cmdparse import Script - from .vendor.pexpect.exceptions import EOF, TIMEOUT - from .vendor import delegator from . import resolver - from ._compat import decode_output import json if not deps: - return [] + return [], [] req_dir = create_tracked_tempdir(prefix="pipenv", suffix="requirements") cmd = [ @@ -509,29 +537,8 @@ def venv_resolve_deps( os.environ["PIPENV_VERBOSITY"] = str(environments.PIPENV_VERBOSITY) os.environ["PIPENV_REQ_DIR"] = fs_str(req_dir) os.environ["PIP_NO_INPUT"] = fs_str("1") - out = to_native_string("") - EOF.__module__ = "pexpect.exceptions" with create_spinner(text=fs_str("Locking...")) as sp: - c = delegator.run(Script.parse(cmd).cmdify(), block=False, env=os.environ.copy()) - _out = decode_output("") - result = None - while True: - try: - result = c.expect(u"\n", timeout=environments.PIPENV_TIMEOUT) - except (EOF, TIMEOUT): - pass - if result is None: - break - _out = c.subprocess.before - if _out is not None: - _out = decode_output("{0}".format(_out)) - out += _out - sp.text = to_native_string("{0}".format(_out[:100])) - if environments.is_verbose(): - if _out is not None: - sp._hide_cursor() - sp.write(_out.rstrip()) - sp._show_cursor() + c = resolve(cmd, sp) c.block() if c.return_code != 0: sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format( @@ -540,17 +547,39 @@ def venv_resolve_deps( click_echo(c.out.strip(), err=True) click_echo(c.err.strip(), err=True) sys.exit(c.return_code) + results = c.out + if vcs_deps: + with temp_environ(): + os.environ["PIPENV_PACKAGES"] = str("\n".join(vcs_deps)) + vcs_c = resolve(cmd, sp) + c.block() + if c.return_code != 0: + sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format( + "Locking Failed!" + )) + click_echo(c.out.strip(), err=True) + click_echo(c.err.strip(), err=True) + sys.exit(c.return_code) + vcs_results = vcs_c.out + vcs_err = vcs_c.err else: - sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!")) + vcs_results = "" + vcs_err = "" + sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!")) + outputs = [results, vcs_results] if environments.is_verbose(): - click_echo(c.out.split("RESULTS:")[0], err=True) + for output in outputs: + click_echo(output.split("RESULTS:")[0], err=True) try: - return json.loads(c.out.split("RESULTS:")[1].strip()) + results = json.loads(results.split("RESULTS:")[1].strip()) + vcs_results = json.loads(vcs_results.split("RESULTS:")[1].strip()) except (IndexError, JSONDecodeError): - click_echo(c.out.strip(), err=True) - click_echo(c.err.strip(), err=True) + for out, err in [(c.out, c.err), (vcs_results, vcs_err)]: + click_echo(out.strip(), err=True) + click_echo(err.strip(), err=True) raise RuntimeError("There was a problem with locking.") + return results, vcs_results def resolve_deps(