From 466707bd85fb271a8ed017b488a541f1d1d48eed Mon Sep 17 00:00:00 2001 From: Frost Ming Date: Mon, 9 Nov 2020 12:34:44 +0800 Subject: [PATCH] Show waring about what happened when a dep is skipped --- news/4346.feature.rst | 1 + pipenv/utils.py | 21 +++++++++++++++++++-- tests/integration/test_lock.py | 16 +++++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 news/4346.feature.rst diff --git a/news/4346.feature.rst b/news/4346.feature.rst new file mode 100644 index 0000000000..0b9b3ae2c2 --- /dev/null +++ b/news/4346.feature.rst @@ -0,0 +1 @@ +Show warning message when a dependency is skipped in locking due to the mismatch of its markers. diff --git a/pipenv/utils.py b/pipenv/utils.py index 5c5be9ebbf..abf7b13af0 100644 --- a/pipenv/utils.py +++ b/pipenv/utils.py @@ -528,9 +528,10 @@ def get_deps_from_line(cls, line): @classmethod def get_deps_from_req(cls, req, resolver=None): # type: (Requirement, Optional["Resolver"]) -> Tuple[Set[str], Dict[str, Dict[str, Union[str, bool, List[str]]]]] + from .patched.piptools.exceptions import NoCandidateFound from .vendor.requirementslib.models.utils import _requirement_to_str_lowercase_name from .vendor.requirementslib.models.requirements import Requirement - from requirementslib.utils import is_installable_dir + from .vendor.requirementslib.utils import is_installable_dir # TODO: this is way too complex, refactor this constraints = set() # type: Set[str] locked_deps = dict() # type: Dict[str, Dict[str, Union[str, bool, List[str]]]] @@ -607,13 +608,27 @@ def get_deps_from_req(cls, req, resolver=None): req.requirement.marker and not req.requirement.marker.evaluate() ): pypi = resolver.repository if resolver else None - best_match = pypi.find_best_match(req.ireq) if pypi else None + try: + best_match = pypi.find_best_match(req.ireq) if pypi else None + except NoCandidateFound: + best_match = None if best_match: hashes = resolver.collect_hashes(best_match) if resolver else [] new_req = Requirement.from_ireq(best_match) new_req = new_req.add_hashes(hashes) name, entry = new_req.pipfile_entry locked_deps[pep423_name(name)] = translate_markers(entry) + click_echo( + "{} doesn't match your environment, " + "its dependencies won't be resolved.".format(req.as_line()), + err=True + ) + else: + click_echo( + "Could not find a version of {} that matches your environment, " + "it will be skipped.".format(req.as_line()), + err=True + ) return constraints, locked_deps constraints.add(req.constraint_line) return constraints, locked_deps @@ -1324,6 +1339,8 @@ def venv_resolve_deps( results = c.out.strip() if c.ok: sp.green.ok(environments.PIPENV_SPINNER_OK_TEXT.format("Success!")) + if c.out.strip(): + click_echo(crayons.yellow("Warning: {0}".format(c.out.strip())), err=True) else: sp.red.fail(environments.PIPENV_SPINNER_FAIL_TEXT.format("Locking Failed!")) click_echo("Output: {0}".format(c.out.strip()), err=True) diff --git a/tests/integration/test_lock.py b/tests/integration/test_lock.py index 2f7e0bd06a..26fdd11c7f 100644 --- a/tests/integration/test_lock.py +++ b/tests/integration/test_lock.py @@ -105,13 +105,27 @@ def test_keep_outdated_doesnt_remove_lockfile_entries(PipenvInstance): with PipenvInstance(chdir=True) as p: p._pipfile.add("requests", "==2.18.4") p._pipfile.add("colorama", {"version": "*", "markers": "os_name=='FakeOS'"}) - p.pipenv("install") + c = p.pipenv("install") + assert c.ok + assert "doesn't match your environment, its dependencies won't be resolved." in c.err p._pipfile.add("six", "*") p.pipenv("lock --keep-outdated") assert "colorama" in p.lockfile["default"] assert p.lockfile["default"]["colorama"]["markers"] == "os_name == 'FakeOS'" +@pytest.mark.lock +def test_resolve_skip_unmatched_requirements(PipenvInstance): + with PipenvInstance(chdir=True) as p: + p._pipfile.add("missing-package", {"markers": "os_name=='FakeOS'"}) + c = p.pipenv("lock") + assert c.ok + assert ( + "Could not find a version of missing-package; " + "os_name == 'FakeOS' that matches your environment" + ) in c.err + + @pytest.mark.lock @pytest.mark.keep_outdated def test_keep_outdated_doesnt_upgrade_pipfile_pins(PipenvInstance):