def test_it_provides_the_correct_solution(): from poetry.mixology.solutions.solutions import PythonRequirementSolution incompatibility = Incompatibility( [Term(Dependency("foo", "^1.0"), True)], PythonCause("^3.5", ">=3.6") ) exception = SolverProblemError(SolveFailure(incompatibility)) solution = PythonRequirementSolution(exception) title = "Check your dependencies Python requirement." description = """\ The Python requirement can be specified via the `python` or `markers` properties For foo, a possible solution would be to set the `python` property to ">=3.6,<4.0"\ """ links = [ "https://python-poetry.org/docs/dependency-specification/#python-restricted-dependencies", "https://python-poetry.org/docs/dependency-specification/#using-environment-markers", ] assert title == solution.solution_title assert ( description == BufferedIO().remove_format(solution.solution_description).strip() ) assert links == solution.documentation_links
def incompatibilities_for( self, package ): # type: (DependencyPackage) -> List[Incompatibility] """ Returns incompatibilities that encapsulate a given package's dependencies, or that it can't be safely selected. If multiple subsequent versions of this package have the same dependencies, this will return incompatibilities that reflect that. It won't return incompatibilities that have already been returned by a previous call to _incompatibilities_for(). """ if package.is_root(): dependencies = package.all_requires else: dependencies = package.requires if not package.python_constraint.allows_all( self._package.python_constraint ): transitive_python_constraint = get_python_constraint_from_marker( package.dependency.transitive_marker ) intersection = package.python_constraint.intersect( transitive_python_constraint ) difference = transitive_python_constraint.difference(intersection) if ( transitive_python_constraint.is_any() or self._package.python_constraint.intersect( package.dependency.python_constraint ).is_empty() or intersection.is_empty() or not difference.is_empty() ): return [ Incompatibility( [Term(package.to_dependency(), True)], PythonCause( package.python_versions, self._package.python_versions ), ) ] dependencies = [ dep for dep in dependencies if dep.name not in self.UNSAFE_PACKAGES and self._package.python_constraint.allows_any(dep.python_constraint) ] return [ Incompatibility( [Term(package.to_dependency(), True), Term(dep, False)], DependencyCause(), ) for dep in dependencies ]
def incompatibilities_for( self, package: DependencyPackage) -> list[Incompatibility]: """ Returns incompatibilities that encapsulate a given package's dependencies, or that it can't be safely selected. If multiple subsequent versions of this package have the same dependencies, this will return incompatibilities that reflect that. It won't return incompatibilities that have already been returned by a previous call to _incompatibilities_for(). """ if package.is_root(): dependencies = package.all_requires else: dependencies = package.requires if not package.python_constraint.allows_all( self._python_constraint): transitive_python_constraint = get_python_constraint_from_marker( package.dependency.transitive_marker) intersection = package.python_constraint.intersect( transitive_python_constraint) difference = transitive_python_constraint.difference( intersection) # The difference is only relevant if it intersects # the root package python constraint difference = difference.intersect(self._python_constraint) if (transitive_python_constraint.is_any() or self._python_constraint.intersect( package.dependency.python_constraint).is_empty() or intersection.is_empty() or not difference.is_empty()): return [ Incompatibility( [Term(package.to_dependency(), True)], PythonCause(package.python_versions, str(self._python_constraint)), ) ] _dependencies = [ dep for dep in dependencies if dep.name not in self.UNSAFE_PACKAGES and self._python_constraint.allows_any(dep.python_constraint) and ( not self._env or dep.marker.validate(self._env.marker_env)) ] dependencies = self._get_dependencies_with_overrides( _dependencies, package) return [ Incompatibility( [Term(package.to_dependency(), True), Term(dep, False)], DependencyCause(), ) for dep in dependencies ]
def test_it_can_solve_python_incompatibility_solver_errors(): from poetry.mixology.solutions.providers import PythonRequirementSolutionProvider from poetry.mixology.solutions.solutions import PythonRequirementSolution incompatibility = Incompatibility([Term(Dependency("foo", "^1.0"), True)], PythonCause("^3.5", ">=3.6")) exception = SolverProblemError(SolveFailure(incompatibility)) provider = PythonRequirementSolutionProvider() assert provider.can_solve(exception) assert isinstance( provider.get_solutions(exception)[0], PythonRequirementSolution)
def incompatibilities_for( self, package): # type: (Package) -> List[Incompatibility] """ Returns incompatibilities that encapsulate a given package's dependencies, or that it can't be safely selected. If multiple subsequent versions of this package have the same dependencies, this will return incompatibilities that reflect that. It won't return incompatibilities that have already been returned by a previous call to _incompatibilities_for(). """ if package.is_root(): dependencies = package.all_requires else: dependencies = package.requires if not self._package.python_constraint.allows_any( package.python_constraint): return [ Incompatibility( [Term(package.to_dependency(), True)], PythonCause(package.python_versions, self._package.python_versions), ) ] if not self._package.platform_constraint.matches( package.platform_constraint): return [ Incompatibility( [Term(package.to_dependency(), True)], PlatformCause(package.platform), ) ] dependencies = [ dep for dep in dependencies if dep.name not in self.UNSAFE_PACKAGES and self._package. python_constraint.allows_any(dep.python_constraint) and self._package.platform_constraint.matches(dep.platform_constraint) ] return [ Incompatibility( [Term(package.to_dependency(), True), Term(dep, False)], DependencyCause(), ) for dep in dependencies ]
def incompatibilities_for( self, package): # type: (Package) -> List[Incompatibility] """ Returns incompatibilities that encapsulate a given package's dependencies, or that it can't be safely selected. If multiple subsequent versions of this package have the same dependencies, this will return incompatibilities that reflect that. It won't return incompatibilities that have already been returned by a previous call to _incompatibilities_for(). """ if package.source_type in ['git', 'file', 'directory']: dependencies = package.requires elif package.is_root(): dependencies = package.all_requires else: dependencies = self._dependencies_for(package) if not self._package.python_constraint.allows_any( package.python_constraint): return [ Incompatibility([Term(package.to_dependency(), True)], PythonCause(package.python_versions)) ] if not self._package.platform_constraint.matches( package.platform_constraint): return [ Incompatibility([Term(package.to_dependency(), True)], PlatformCause(package.platform)) ] return [ Incompatibility( [Term(package.to_dependency(), True), Term(dep, False)], DependencyCause()) for dep in dependencies ]