diff --git a/news/4386.bugfix.rst b/news/4386.bugfix.rst new file mode 100644 index 00000000..ff633fb9 --- /dev/null +++ b/news/4386.bugfix.rst @@ -0,0 +1 @@ +Fix a bug that non-wheel file requirements can be resolved successfully. diff --git a/news/4441.feature.rst b/news/4441.feature.rst new file mode 100644 index 00000000..3836516c --- /dev/null +++ b/news/4441.feature.rst @@ -0,0 +1 @@ +Add the missing ``--system`` option to ``pipenv sync``. diff --git a/news/4443.feature.rst b/news/4443.feature.rst new file mode 100644 index 00000000..ea4a0c06 --- /dev/null +++ b/news/4443.feature.rst @@ -0,0 +1,2 @@ +Add a new option pair ``--header/--no-header`` to ``pipenv lock`` command, +which adds a header to the generated requirements.txt diff --git a/pipenv/cli/options.py b/pipenv/cli/options.py index b96a03f6..35af39ca 100644 --- a/pipenv/cli/options.py +++ b/pipenv/cli/options.py @@ -440,6 +440,7 @@ def lock_options(f): f = install_base_options(f) f = lock_dev_option(f) f = emit_requirements_flag(f) + f = emit_requirements_header_flag(f) f = dev_only_flag(f) return f diff --git a/pipenv/core.py b/pipenv/core.py index 9ba7cf7a..b072d649 100644 --- a/pipenv/core.py +++ b/pipenv/core.py @@ -841,15 +841,15 @@ def do_install_dependencies( dev = dev or dev_only deps_list = list(lockfile.get_requirements(dev=dev, only=dev_only)) if emit_requirements: - index_args = prepare_pip_source_args(get_source_list(pypi_mirror=pypi_mirror, project=project)) + index_args = prepare_pip_source_args( + get_source_list(pypi_mirror=pypi_mirror, project=project) + ) index_args = " ".join(index_args).replace(" -", "\n-") deps = [ req.as_line(sources=False, include_hashes=False) for req in deps_list ] click.echo(index_args) - click.echo( - "\n".join(sorted(deps)) - ) + click.echo("\n".join(sorted(deps))) sys.exit(0) if concurrent: nprocs = PIPENV_MAX_SUBPROCESS diff --git a/pipenv/resolver.py b/pipenv/resolver.py index 733b28d5..b06deca6 100644 --- a/pipenv/resolver.py +++ b/pipenv/resolver.py @@ -504,55 +504,6 @@ class Entry(object): """ if self.is_in_pipfile: return self.pipfile_entry.as_ireq() - return self.constraint_from_parent_conflicts() - - def constraint_from_parent_conflicts(self): - """ - Given a resolved entry with multiple parent dependencies with different - constraints, searches for the resolution that satisfies all of the parent - constraints. - - :return: A new **InstallRequirement** satisfying all parent constraints - :raises: :exc:`~pipenv.exceptions.DependencyConflict` if resolution is impossible - """ - # ensure that we satisfy the parent dependencies of this dep - parent_dependencies = set() - has_mismatch = False - can_use_original = True - for p in self.parent_deps: - # updated dependencies should be satisfied since they were resolved already - if p.is_updated: - continue - # parents with no requirements can't conflict - if not p.requirements: - continue - entry_ref = p.get_dependency(self.name) - required = entry_ref.get("required_version", "*") - required = self.clean_specifier(required) - parent_requires = self.make_requirement(self.name, required) - parent_dependencies.add("{0} => {1} ({2})".format(p.name, self.name, required)) - # use pre=True here or else prereleases dont satisfy constraints - if parent_requires.requirement.specifier and ( - not parent_requires.requirement.specifier.contains(self.original_version, prereleases=True) - ): - can_use_original = False - if parent_requires.requirement.specifier and ( - not parent_requires.requirement.specifier.contains(self.updated_version, prereleases=True) - ): - if not self.entry.editable and self.updated_version != self.original_version: - has_mismatch = True - if has_mismatch and not can_use_original: - from pipenv.exceptions import DependencyConflict - msg = ( - "Cannot resolve {0} ({1}) due to conflicting parent dependencies: " - "\n\t{2}".format( - self.name, self.updated_version, "\n\t".join(parent_dependencies) - ) - ) - raise DependencyConflict(msg) - elif can_use_original: - return self.lockfile_entry.as_ireq() - return self.entry.as_ireq() def validate_constraints(self): """ @@ -562,19 +513,24 @@ class Entry(object): :return: True if the constraints are satisfied by the resolution provided :raises: :exc:`pipenv.exceptions.DependencyConflict` if the constraints dont exist """ + from pipenv.exceptions import DependencyConflict + from pipenv.environments import is_verbose + constraints = self.get_constraints() + pinned_version = self.updated_version for constraint in constraints: - try: - constraint.check_if_exists(False) - except Exception: - from pipenv.exceptions import DependencyConflict - from pipenv.environments import is_verbose + if not constraint.req: + continue + if pinned_version and not constraint.req.specifier.contains( + str(pinned_version), prereleases=True + ): if is_verbose(): print("Tried constraint: {0!r}".format(constraint), file=sys.stderr) msg = ( "Cannot resolve conflicting version {0}{1} while {2}{3} is " "locked.".format( - self.name, self.updated_specifier, self.old_name, self.old_specifiers + self.name, constraint.req.specifier, + self.name, self.updated_specifier ) ) raise DependencyConflict(msg)