diff --git a/pipenv/cli/command.py b/pipenv/cli/command.py index 04e72ca0ba..e1b94be130 100644 --- a/pipenv/cli/command.py +++ b/pipenv/cli/command.py @@ -243,8 +243,6 @@ def install(state, **kwargs): requirementstxt=state.installstate.requirementstxt, pre=state.installstate.pre, deploy=state.installstate.deploy, - keep_outdated=state.installstate.keep_outdated, - selective_upgrade=state.installstate.selective_upgrade, index_url=state.index, packages=state.installstate.packages, editable_packages=state.installstate.editables, @@ -321,7 +319,6 @@ def uninstall(ctx, state, all_dev=False, all=False, **kwargs): lock=not state.installstate.skip_lock, all_dev=all_dev, all=all, - keep_outdated=state.installstate.keep_outdated, pypi_mirror=state.pypi_mirror, categories=state.installstate.categories, ctx=ctx, @@ -370,7 +367,6 @@ def lock(ctx, state, **kwargs): state.project, clear=state.clear, pre=pre, - keep_outdated=state.installstate.keep_outdated, pypi_mirror=state.pypi_mirror, write=not state.quiet, categories=state.installstate.categories, @@ -583,7 +579,6 @@ def update(ctx, state, bare=False, dry_run=None, outdated=False, **kwargs): clear=state.clear, pre=state.installstate.pre, pypi_mirror=state.pypi_mirror, - keep_outdated=state.installstate.keep_outdated, system=False, packages=state.installstate.packages, editable_packages=state.installstate.editables, @@ -679,7 +674,6 @@ def sync(ctx, state, bare=False, user=False, unused=False, **kwargs): dev=state.installstate.dev, python=state.python, bare=bare, - dont_upgrade=(not state.installstate.keep_outdated), user=user, clear=state.clear, unused=unused, diff --git a/pipenv/cli/options.py b/pipenv/cli/options.py index d698311916..7ff0a1f2e1 100644 --- a/pipenv/cli/options.py +++ b/pipenv/cli/options.py @@ -3,7 +3,6 @@ from pipenv.project import Project from pipenv.utils.internet import is_valid_url -from pipenv.vendor import click from pipenv.vendor.click import ( BadArgumentUsage, BadParameter, @@ -77,8 +76,6 @@ class InstallState: def __init__(self): self.dev = False self.pre = False - self.selective_upgrade = False - self.keep_outdated = False self.skip_lock = False self.ignore_pipfile = False self.code = False @@ -151,59 +148,6 @@ def callback(ctx, param, value): )(f) -def keep_outdated_option(f): - def callback(ctx, param, value): - state = ctx.ensure_object(State) - state.installstate.keep_outdated = value - if value: - click.secho( - "The flag --keep-outdated has been deprecated for removal. " - "The flag does not respect package resolver results and leads to inconsistent lock files. " - "Consider using the new `pipenv upgrade` command to selectively upgrade packages.", - fg="yellow", - bold=True, - err=True, - ) - return value - - return option( - "--keep-outdated", - is_flag=True, - default=False, - expose_value=False, - help="Keep out-dated dependencies from being updated in Pipfile.lock.", - callback=callback, - type=click_types.BOOL, - show_envvar=True, - )(f) - - -def selective_upgrade_option(f): - def callback(ctx, param, value): - state = ctx.ensure_object(State) - state.installstate.selective_upgrade = value - if value: - click.secho( - "The flag --selective-upgrade has been deprecated for removal. " - "The flag is buggy and leads to inconsistent lock files. " - "Consider using the new `pipenv upgrade` command to selectively upgrade packages.", - fg="yellow", - bold=True, - err=True, - ) - return value - - return option( - "--selective-upgrade", - is_flag=True, - default=False, - type=click_types.BOOL, - help="Update specified packages.", - callback=callback, - expose_value=False, - )(f) - - def ignore_pipfile_option(f): def callback(ctx, param, value): state = ctx.ensure_object(State) @@ -571,7 +515,6 @@ def common_options(f): def install_base_options(f): f = common_options(f) f = pre_option(f) - f = keep_outdated_option(f) f = extra_pip_args(f) return f @@ -605,7 +548,6 @@ def install_options(f): f = sync_options(f) f = index_option(f) f = requirementstxt_option(f) - f = selective_upgrade_option(f) f = ignore_pipfile_option(f) f = editable_option(f) f = package_arg(f) diff --git a/pipenv/resolver.py b/pipenv/resolver.py index 234af7ca68..5b072bb9d0 100644 --- a/pipenv/resolver.py +++ b/pipenv/resolver.py @@ -229,12 +229,8 @@ def marker_to_str(marker): return marker_str return None - def get_cleaned_dict(self, keep_outdated=False): - if keep_outdated and self.is_updated: - self.validate_constraints() - self.ensure_least_updates_possible() - elif not keep_outdated: - self.validate_constraints() + def get_cleaned_dict(self): + self.validate_constraints() if self.entry.extras != self.lockfile_entry.extras: entry_extras = list(self.entry.extras) if self.lockfile_entry.extras: @@ -626,65 +622,7 @@ def clean_results(results, resolver, project, category): reverse_deps=reverse_deps, category=category, ) - entry_dict = translate_markers(entry.get_cleaned_dict(keep_outdated=False)) - new_results.append(entry_dict) - return new_results - - -def clean_outdated(results, resolver, project, category): - from pipenv.utils.dependencies import get_lockfile_section_using_pipfile_category - - if not project.lockfile_exists: - return results - lockfile = project.lockfile_content - lockfile_section = get_lockfile_section_using_pipfile_category(category) - reverse_deps = project.environment.reverse_dependencies() - new_results = [r for r in results if r["name"] not in lockfile[lockfile_section]] - for result in results: - name = result.get("name") - entry_dict = result.copy() - entry = Entry( - name, - entry_dict, - project, - resolver, - reverse_deps=reverse_deps, - category=category, - ) - # The old entry was editable but this one isnt; prefer the old one - # TODO: Should this be the case for all locking? - if entry.was_editable and not entry.is_editable: - continue - lockfile_entry = lockfile[lockfile_section].get(name, None) - if not lockfile_entry: - if name in lockfile[lockfile_section]: - lockfile_entry = lockfile[lockfile_section][name] - if lockfile_entry and not entry.is_updated: - old_markers = next( - iter( - m - for m in ( - entry.lockfile_entry.markers, - lockfile_entry.get("markers", None), - ) - if m is not None - ), - None, - ) - new_markers = entry_dict.get("markers", None) - if old_markers: - old_markers = Entry.marker_to_str(old_markers) - if old_markers and not new_markers: - entry.markers = old_markers - elif new_markers and not old_markers: - del entry.entry_dict["markers"] - entry._entry.req.req.marker = None - entry._entry.markers = None - # if the entry has not changed versions since the previous lock, - # don't introduce new markers since that is more restrictive - # if entry.has_markers and not entry.had_markers and not entry.is_updated: - # do make sure we retain the original markers for entries that are not changed - entry_dict = entry.get_cleaned_dict(keep_outdated=True) + entry_dict = translate_markers(entry.get_cleaned_dict()) new_results.append(entry_dict) return new_results @@ -755,7 +693,6 @@ def resolve( if pypi_mirror_source else project.pipfile_sources() ) - keep_outdated = os.environ.get("PIPENV_KEEP_OUTDATED", False) results, resolver = resolve( packages, pre=pre, @@ -766,10 +703,7 @@ def resolve( system=system, requirements_dir=requirements_dir, ) - if keep_outdated: - results = clean_outdated(results, resolver, project, category) - else: - results = clean_results(results, resolver, project, category) + results = clean_results(results, resolver, project, category) if write: with open(write, "w") as fh: if not results: diff --git a/pipenv/routines/clean.py b/pipenv/routines/clean.py index eec588b37e..cbb3b0493b 100644 --- a/pipenv/routines/clean.py +++ b/pipenv/routines/clean.py @@ -63,10 +63,8 @@ def do_clean( sys.exit(int(failure)) -def ensure_lockfile(project, keep_outdated=False, pypi_mirror=None): +def ensure_lockfile(project, pypi_mirror=None): """Ensures that the lockfile is up-to-date.""" - if not keep_outdated: - keep_outdated = project.settings.get("keep_outdated") # Write out the lockfile if it doesn't exist, but not if the Pipfile is being ignored if project.lockfile_exists: old_hash = project.get_lockfile_hash() @@ -80,6 +78,6 @@ def ensure_lockfile(project, keep_outdated=False, pypi_mirror=None): bold=True, err=True, ) - do_lock(project, keep_outdated=keep_outdated, pypi_mirror=pypi_mirror) + do_lock(project, pypi_mirror=pypi_mirror) else: - do_lock(project, keep_outdated=keep_outdated, pypi_mirror=pypi_mirror) + do_lock(project, pypi_mirror=pypi_mirror) diff --git a/pipenv/routines/install.py b/pipenv/routines/install.py index 3ef79c2542..6a5d035b8b 100644 --- a/pipenv/routines/install.py +++ b/pipenv/routines/install.py @@ -9,7 +9,6 @@ from pipenv.patched.pip._internal.exceptions import PipError from pipenv.patched.pip._vendor import rich from pipenv.routines.lock import do_lock -from pipenv.utils.dependencies import convert_deps_to_pip, is_star from pipenv.utils.indexes import get_source_list from pipenv.utils.internet import download_file, is_valid_url from pipenv.utils.pip import ( @@ -43,8 +42,6 @@ def do_install( requirementstxt=False, pre=False, deploy=False, - keep_outdated=False, - selective_upgrade=False, site_packages=None, extra_pip_args=None, categories=None, @@ -53,8 +50,6 @@ def do_install( suffix="-requirements", prefix="pipenv-" ) warnings.filterwarnings("default", category=ResourceWarning) - if selective_upgrade: - keep_outdated = True packages = packages if packages else [] editable_packages = editable_packages if editable_packages else [] package_args = [p for p in packages if p] + [p for p in editable_packages if p] @@ -82,8 +77,6 @@ def do_install( # Load the --pre settings from the Pipfile. if not pre: pre = project.settings.get("allow_prereleases") - if not keep_outdated: - keep_outdated = project.settings.get("keep_outdated") remote = requirementstxt and is_valid_url(requirementstxt) if "default" in categories: raise exceptions.PipenvUsageError( @@ -166,30 +159,12 @@ def do_install( # Allow more than one package to be provided. package_args = [p for p in packages] + [f"-e {pkg}" for pkg in editable_packages] - # Support for --selective-upgrade. - # We should do this part first to make sure that we actually do selectively upgrade - # the items specified - if selective_upgrade: - from pipenv.vendor.requirementslib.models.requirements import Requirement - - for i, package in enumerate(package_args[:]): - section = project.packages if not dev else project.dev_packages - package = Requirement.from_line(package) - package__name, package__val = package.pipfile_entry - try: - if not is_star(section[package__name]) and is_star(package__val): - # Support for VCS dependencies. - package_args[i] = convert_deps_to_pip( - {package__name: section[package__name]}, project=project - )[0] - except KeyError: - pass # Install all dependencies, if none was provided. # This basically ensures that we have a pipfile and lockfile, then it locks and # installs from the lockfile new_packages = [] if not packages and not editable_packages: - # Update project settings with pre preference. + # Update project settings with prerelease preference. if pre: project.update_settings({"allow_prereleases": pre}) do_init( @@ -203,7 +178,6 @@ def do_install( pre=pre, requirements_dir=requirements_directory, pypi_mirror=pypi_mirror, - keep_outdated=keep_outdated, extra_pip_args=extra_pip_args, categories=categories, ) @@ -220,7 +194,6 @@ def do_install( dev=dev, system=system, allow_global=system, - keep_outdated=keep_outdated, requirements_dir=requirements_directory, deploy=deploy, pypi_mirror=pypi_mirror, @@ -324,7 +297,6 @@ def do_install( dev=dev, system=system, allow_global=system, - keep_outdated=keep_outdated, requirements_dir=requirements_directory, deploy=deploy, pypi_mirror=pypi_mirror, @@ -345,7 +317,6 @@ def do_sync( dev=False, python=None, bare=False, - dont_upgrade=False, user=False, clear=False, unused=False, @@ -709,7 +680,6 @@ def do_init( system=False, deploy=False, pre=False, - keep_outdated=False, requirements_dir=None, pypi_mirror=None, extra_pip_args=None, @@ -775,7 +745,6 @@ def do_init( project, system=system, pre=pre, - keep_outdated=keep_outdated, write=True, pypi_mirror=pypi_mirror, categories=categories, @@ -801,7 +770,6 @@ def do_init( project, system=system, pre=pre, - keep_outdated=keep_outdated, write=True, pypi_mirror=pypi_mirror, categories=categories, diff --git a/pipenv/routines/lock.py b/pipenv/routines/lock.py index f81833c923..67dab9b3fc 100644 --- a/pipenv/routines/lock.py +++ b/pipenv/routines/lock.py @@ -1,9 +1,5 @@ -from pipenv import exceptions -from pipenv.patched.pip._vendor.packaging.utils import canonicalize_name from pipenv.utils.dependencies import ( - get_lockfile_section_using_pipfile_category, get_pipfile_category_using_lockfile_section, - is_pinned, ) from pipenv.vendor import click @@ -13,22 +9,13 @@ def do_lock( system=False, clear=False, pre=False, - keep_outdated=False, write=True, pypi_mirror=None, categories=None, ): """Executes the freeze functionality.""" - cached_lockfile = {} if not pre: pre = project.settings.get("allow_prereleases") - if keep_outdated: - if not project.lockfile_exists: - raise exceptions.PipenvOptionsError( - "--keep-outdated", - message="Pipfile.lock must exist to use --keep-outdated!", - ) - cached_lockfile = project.lockfile_content # Cleanup lockfile. if not categories: lockfile_categories = project.get_package_categories(for_lockfile=True) @@ -67,11 +54,10 @@ def do_lock( ) # Prune old lockfile category as new one will be created. - if not keep_outdated: - try: - del lockfile[category] - except KeyError: - pass + try: + del lockfile[category] + except KeyError: + pass from pipenv.utils.resolver import venv_resolve_deps @@ -87,29 +73,8 @@ def do_lock( pypi_mirror=pypi_mirror, pipfile=packages, lockfile=lockfile, - keep_outdated=keep_outdated, ) - # Support for --keep-outdated... - if keep_outdated: - for category_name in project.get_package_categories(): - category = project.get_pipfile_section(category_name) - lockfile_section = get_lockfile_section_using_pipfile_category(category_name) - - for package_specified in category.keys(): - if not is_pinned(category[package_specified]): - canonical_name = canonicalize_name(package_specified) - if canonical_name in cached_lockfile[lockfile_section]: - lockfile[lockfile_section][canonical_name] = cached_lockfile[ - lockfile_section - ][canonical_name].copy() - packages = set(cached_lockfile[lockfile_section].keys()) - new_lockfile = set(lockfile[lockfile_section].keys()) - missing = packages - new_lockfile - for missing_pkg in missing: - lockfile[lockfile_section][missing_pkg] = cached_lockfile[ - lockfile_section - ][missing_pkg].copy() # Overwrite any category packages with default packages. for category in lockfile_categories: if category == "default": diff --git a/pipenv/routines/uninstall.py b/pipenv/routines/uninstall.py index 1ca70b619f..2de5e7bc6b 100644 --- a/pipenv/routines/uninstall.py +++ b/pipenv/routines/uninstall.py @@ -28,7 +28,6 @@ def do_uninstall( lock=False, all_dev=False, all=False, - keep_outdated=False, pypi_mirror=None, ctx=None, categories=None, @@ -167,9 +166,7 @@ def do_uninstall( failure = True if lock: - do_lock( - project, system=system, keep_outdated=keep_outdated, pypi_mirror=pypi_mirror - ) + do_lock(project, system=system, pypi_mirror=pypi_mirror) sys.exit(int(failure)) diff --git a/pipenv/routines/update.py b/pipenv/routines/update.py index 60d56e71f8..22e1e4aedb 100644 --- a/pipenv/routines/update.py +++ b/pipenv/routines/update.py @@ -33,7 +33,6 @@ def do_update( bare=False, dry_run=None, outdated=False, - keep_outdated=False, clear=False, lock_only=False, ): @@ -70,7 +69,6 @@ def do_update( project, clear=clear, pre=pre, - keep_outdated=keep_outdated, pypi_mirror=pypi_mirror, write=not quiet, ) @@ -94,7 +92,6 @@ def do_update( categories=categories, python=python, bare=bare, - dont_upgrade=not keep_outdated, user=False, clear=clear, unused=False, @@ -164,7 +161,6 @@ def upgrade( pre=pre, allow_global=system, pypi_mirror=pypi_mirror, - keep_outdated=False, ) if not upgrade_lock_data: click.echo("Nothing to upgrade!") @@ -195,7 +191,6 @@ def upgrade( pre=pre, allow_global=system, pypi_mirror=pypi_mirror, - keep_outdated=False, ) # Mutate the existing lockfile with the upgrade data for the categories for package_name, _ in upgrade_lock_data.items(): diff --git a/pipenv/utils/pip.py b/pipenv/utils/pip.py index c77bfb5780..142341ab41 100644 --- a/pipenv/utils/pip.py +++ b/pipenv/utils/pip.py @@ -82,7 +82,6 @@ def pip_install_deps( allow_global=False, ignore_hashes=False, no_deps=False, - selective_upgrade=False, requirements_dir=None, use_pep517=True, extra_pip_args: Optional[List] = None, @@ -166,7 +165,6 @@ def pip_install_deps( pre=project.settings.get("allow_prereleases", False), verbose=False, # When True, the subprocess fails to recognize the EOF when reading stdout. upgrade=True, - selective_upgrade=False, no_use_pep517=not use_pep517, no_deps=no_deps, extra_pip_args=extra_pip_args, @@ -192,8 +190,6 @@ def pip_install_deps( click.secho(f"$ {cmd_list_to_shell(pip_command)}", fg="cyan", err=True) cache_dir = Path(project.s.PIPENV_CACHE_DIR) default_exists_action = "w" - if selective_upgrade: - default_exists_action = "i" exists_action = project.s.PIP_EXISTS_ACTION or default_exists_action pip_config = { "PIP_CACHE_DIR": cache_dir.as_posix(), @@ -236,7 +232,6 @@ def pip_install( index=None, pre=False, dev=False, - selective_upgrade=False, requirements_dir=None, extra_indexes=None, pypi_mirror=None, @@ -314,7 +309,6 @@ def pip_install( pre=pre, verbose=project.s.is_verbose(), upgrade=True, - selective_upgrade=selective_upgrade, no_use_pep517=not use_pep517, no_deps=no_deps, require_hashes=not ignore_hashes, @@ -339,8 +333,6 @@ def pip_install( click.echo(f"$ {cmd_list_to_shell(pip_command)}", err=True) cache_dir = Path(project.s.PIPENV_CACHE_DIR) default_exists_action = "w" - if selective_upgrade: - default_exists_action = "i" exists_action = project.s.PIP_EXISTS_ACTION or default_exists_action pip_config = { "PIP_CACHE_DIR": cache_dir.as_posix(), @@ -367,7 +359,6 @@ def get_pip_args( no_build_isolation: bool = False, no_use_pep517: bool = False, no_deps: bool = False, - selective_upgrade: bool = False, src_dir: Optional[str] = None, extra_pip_args: Optional[List] = None, ) -> List[str]: @@ -379,18 +370,12 @@ def get_pip_args( "no_build_isolation": ["--no-build-isolation"], "no_use_pep517": ["--no-use-pep517"], "no_deps": ["--no-deps"], - "selective_upgrade": [ - "--upgrade-strategy=only-if-needed", - "--exists-action={}".format(project.s.PIP_EXISTS_ACTION or "i"), - ], "src_dir": src_dir, } arg_set = ["--no-input"] if project.settings.get("disable_pip_input", True) else [] for key in arg_map.keys(): if key in locals() and locals().get(key): arg_set.extend(arg_map.get(key)) - elif key == "selective_upgrade" and not locals().get(key): - arg_set.append("--exists-action=i") for extra_pip_arg in extra_pip_args: arg_set.append(extra_pip_arg) return list(dict.fromkeys(arg_set)) diff --git a/pipenv/utils/resolver.py b/pipenv/utils/resolver.py index 5cc689b3b6..f65ecbd355 100644 --- a/pipenv/utils/resolver.py +++ b/pipenv/utils/resolver.py @@ -1004,7 +1004,6 @@ def venv_resolve_deps( pypi_mirror=None, pipfile=None, lockfile=None, - keep_outdated=False, ): """ Resolve dependencies for a pipenv project, acts as a portal to the target environment. @@ -1025,7 +1024,6 @@ def venv_resolve_deps( :param pipfile: A Pipfile section to operate on, defaults to None :type pipfile: Optional[Dict[str, Union[str, Dict[str, bool, List[str]]]]] :param Dict[str, Any] lockfile: A project lockfile to mutate, defaults to None - :param bool keep_outdated: Whether to retain outdated dependencies and resolve with them in mind, defaults to False :raises RuntimeError: Raised on resolution failure :return: The lock data :rtype: dict @@ -1076,8 +1074,6 @@ def venv_resolve_deps( os.environ["PIPENV_SITE_DIR"] = pipenv_site_dir else: os.environ.pop("PIPENV_SITE_DIR", None) - if keep_outdated: - os.environ["PIPENV_KEEP_OUTDATED"] = "1" with console.status("Locking...", spinner=project.s.PIPENV_SPINNER) as st: # This conversion is somewhat slow on local and file-type requirements since # we now download those requirements / make temporary folders to perform diff --git a/tests/integration/test_lock.py b/tests/integration/test_lock.py index cbf33639a7..905ea5855d 100644 --- a/tests/integration/test_lock.py +++ b/tests/integration/test_lock.py @@ -101,59 +101,6 @@ def get_hash(release_name): } -@pytest.mark.lock -@pytest.mark.keep_outdated -def test_lock_keep_outdated(pipenv_instance_pypi): - - with pipenv_instance_pypi() as p: - with open(p.pipfile_path, 'w') as f: - contents = """ -[packages] -requests = {version = "==2.14.0"} -pytest = "==3.1.0" - """.strip() - f.write(contents) - - c = p.pipenv('lock') - assert c.returncode == 0 - lock = p.lockfile - assert 'requests' in lock['default'] - assert lock['default']['requests']['version'] == "==2.14.0" - assert 'pytest' in lock['default'] - assert lock['default']['pytest']['version'] == "==3.1.0" - - with open(p.pipfile_path, 'w') as f: - updated_contents = """ -[packages] -requests = {version = "==2.18.4"} -pytest = "*" - """.strip() - f.write(updated_contents) - - c = p.pipenv('lock --keep-outdated') - assert c.returncode == 0 - lock = p.lockfile - assert 'requests' in lock['default'] - assert lock['default']['requests']['version'] == "==2.18.4" - assert 'pytest' in lock['default'] - assert lock['default']['pytest']['version'] == "==3.1.0" - - -@pytest.mark.lock -@pytest.mark.keep_outdated -def test_keep_outdated_doesnt_remove_lockfile_entries(pipenv_instance_private_pypi): - with pipenv_instance_private_pypi(chdir=True) as p: - p._pipfile.add("requests", {"version": "*", "markers": "os_name=='FakeOS'"}) - p._pipfile.add("colorama", {"version": "*"}) - c = p.pipenv("install") - assert c.returncode == 0 - assert "doesn't match your environment, its dependencies won't be resolved." in c.stderr - p._pipfile.add("six", "*") - p.pipenv("lock --keep-outdated") - assert "requests" in p.lockfile["default"] - assert p.lockfile["default"]["requests"]["markers"] == "os_name == 'FakeOS'" - - @pytest.mark.lock def test_resolve_skip_unmatched_requirements(pipenv_instance_pypi): with pipenv_instance_pypi(chdir=True) as p: @@ -166,58 +113,6 @@ def test_resolve_skip_unmatched_requirements(pipenv_instance_pypi): ) in c.stderr -@pytest.mark.lock -@pytest.mark.keep_outdated -def test_keep_outdated_doesnt_upgrade_pipfile_pins(pipenv_instance_private_pypi): - with pipenv_instance_private_pypi(chdir=True) as p: - p._pipfile.add("urllib3", "==1.21.1") - c = p.pipenv("install") - assert c.returncode == 0 - p._pipfile.add("requests", "==2.18.4") - c = p.pipenv("lock --keep-outdated") - assert c.returncode == 0 - assert "requests" in p.lockfile["default"] - assert "urllib3" in p.lockfile["default"] - assert p.lockfile["default"]["requests"]["version"] == "==2.18.4" - assert p.lockfile["default"]["urllib3"]["version"] == "==1.21.1" - - -@pytest.mark.lock -def test_keep_outdated_keeps_markers_not_removed(pipenv_instance_pypi): - with pipenv_instance_pypi(chdir=True) as p: - c = p.pipenv("install six click") - assert c.returncode == 0 - lockfile = Path(p.lockfile_path) - lockfile_content = lockfile.read_text() - lockfile_json = json.loads(lockfile_content) - assert "six" in lockfile_json["default"] - lockfile_json["default"]["six"]["markers"] = "python_version >= '2.7'" - lockfile.write_text(json.dumps(lockfile_json)) - c = p.pipenv("lock --keep-outdated") - assert c.returncode == 0 - assert p.lockfile["default"]["six"].get("markers", "") == "python_version >= '2.7'" - - -@pytest.mark.lock -@pytest.mark.keep_outdated -def test_keep_outdated_doesnt_update_satisfied_constraints(pipenv_instance_private_pypi): - with pipenv_instance_private_pypi(chdir=True) as p: - p._pipfile.add("requests", "==2.18.4") - c = p.pipenv("install") - assert c.returncode == 0 - p._pipfile.add("requests", "*") - assert p.pipfile["packages"]["requests"] == "*" - c = p.pipenv("lock --keep-outdated") - assert c.returncode == 0 - assert "requests" in p.lockfile["default"] - assert "urllib3" in p.lockfile["default"] - # ensure this didn't update requests - assert p.lockfile["default"]["requests"]["version"] == "==2.18.4" - c = p.pipenv("lock") - assert c.returncode == 0 - assert p.lockfile["default"]["requests"]["version"] != "==2.18.4" - - @pytest.mark.lock @pytest.mark.complex @pytest.mark.needs_internet