def test_to_pep_508_combination(): dependency = Dependency("foo", "^1.2,!=1.3.5") assert "foo (>=1.2,<2.0,!=1.3.5)" == dependency.to_pep_508() dependency = Dependency("foo", "~1.2,!=1.2.5") assert "foo (>=1.2,<1.3,!=1.2.5)" == dependency.to_pep_508()
def test_to_pep_508_combination() -> None: dependency = Dependency("foo", "^1.2,!=1.3.5") assert dependency.to_pep_508() == "foo (>=1.2,<2.0,!=1.3.5)" dependency = Dependency("foo", "~1.2,!=1.2.5") assert dependency.to_pep_508() == "foo (>=1.2,<1.3,!=1.2.5)"
def test_to_pep_508() -> None: dependency = Dependency("Django", "^1.23") result = dependency.to_pep_508() assert result == "Django (>=1.23,<2.0)" dependency = Dependency("Django", "^1.23") dependency.python_versions = "~2.7 || ^3.6" result = dependency.to_pep_508() assert (result == "Django (>=1.23,<2.0); " 'python_version >= "2.7" and python_version < "2.8" ' 'or python_version >= "3.6" and python_version < "4.0"')
def test_to_pep_508_caret(): dependency = Dependency("foo", "^1.2.3") assert "foo (>=1.2.3,<2.0.0)" == dependency.to_pep_508() dependency = Dependency("foo", "^1.2") assert "foo (>=1.2,<2.0)" == dependency.to_pep_508() dependency = Dependency("foo", "^0.2.3") assert "foo (>=0.2.3,<0.3.0)" == dependency.to_pep_508() dependency = Dependency("foo", "^0.2") assert "foo (>=0.2,<0.3)" == dependency.to_pep_508()
def test_to_pep_508_tilde(): dependency = Dependency("foo", "~1.2.3") assert "foo (>=1.2.3,<1.3.0)" == dependency.to_pep_508() dependency = Dependency("foo", "~1.2") assert "foo (>=1.2,<1.3)" == dependency.to_pep_508() dependency = Dependency("foo", "~0.2.3") assert "foo (>=0.2.3,<0.3.0)" == dependency.to_pep_508() dependency = Dependency("foo", "~0.2") assert "foo (>=0.2,<0.3)" == dependency.to_pep_508()
def test_accepts_python_versions() -> None: dependency = Dependency("A", "^1.0") dependency.python_versions = "^3.6" package = Package("A", "1.4") package.python_versions = "~3.6" assert dependency.accepts(package)
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 resolve_source_deps(poetry, package, reqs, frozen=False): # find any source path dev deps and them and their recursive # deps to reqs if poetry.local_config['name'] not in (package.name, package.pretty_name): return source_deps = [] for dep_name, info in poetry.local_config.get('dev-dependencies', {}).items(): if isinstance(info, dict) and 'path' in info: source_deps.append(dep_name) if not source_deps: return from poetry.core.packages.dependency import Dependency dep_map = {d['name']: d for d in poetry.locker.lock_data['package']} seen = set(source_deps) seen.add('setuptools') prefix = '' if frozen else '^' while source_deps: dep = source_deps.pop() if dep not in dep_map: dep = dep.replace('_', '-') version = dep_map[dep]['version'] reqs.append( Dependency(dep, '{}{}'.format(prefix, version)).to_pep_508()) for cdep, cversion in dep_map[dep].get('dependencies', {}).items(): if cdep in seen: continue source_deps.append(cdep) seen.add(cdep)
def install_plugin(installed: Repository) -> None: package = ProjectPackage("poetry-instance", __version__) plugin = Package("poetry-plugin", "1.2.3") package.add_dependency( Dependency(plugin.name, "^1.2.3", groups=[SelfCommand.ADDITIONAL_PACKAGE_GROUP]) ) content = Factory.create_pyproject_from_package(package) system_pyproject_file = SelfCommand.get_default_system_pyproject_file() system_pyproject_file.write_text(content.as_string(), encoding="utf-8") lock_content = { "package": [ { "name": "poetry-plugin", "version": "1.2.3", "category": "main", "optional": False, "platform": "*", "python-versions": "*", "checksum": [], }, ], "metadata": { "python-versions": "^3.6", "platform": "*", "content-hash": "123456789", "hashes": {"poetry-plugin": []}, }, } system_pyproject_file.parent.joinpath("poetry.lock").write_text( tomlkit.dumps(lock_content), encoding="utf-8" ) installed.add_package(plugin)
def test_with_constraint() -> None: dependency = Dependency( "foo", "^1.2.3", optional=True, groups=["dev"], allows_prereleases=True, extras=["bar", "baz"], ) dependency.marker = parse_marker( 'python_version >= "3.6" and python_version < "4.0"') dependency.transitive_marker = parse_marker( 'python_version >= "3.7" and python_version < "4.0"') dependency.python_versions = "^3.6" dependency.transitive_python_versions = "^3.7" new = dependency.with_constraint("^1.2.6") assert new.name == dependency.name assert str(new.constraint) == ">=1.2.6,<2.0.0" assert new.is_optional() assert new.groups == frozenset(["dev"]) assert new.allows_prereleases() assert set(new.extras) == {"bar", "baz"} assert new.marker == dependency.marker assert new.transitive_marker == dependency.transitive_marker assert new.python_constraint == dependency.python_constraint assert new.transitive_python_constraint == dependency.transitive_python_constraint
def _update(self, version: Version) -> None: from poetry.core.packages.dependency import Dependency from poetry.core.packages.project_package import ProjectPackage from poetry.config.config import Config from poetry.installation.installer import Installer from poetry.packages.locker import NullLocker from poetry.repositories.installed_repository import InstalledRepository from poetry.utils.env import EnvManager env = EnvManager.get_system_env(naive=True) installed = InstalledRepository.load(env) root = ProjectPackage("poetry-updater", "0.0.0") root.python_versions = ".".join(str(c) for c in env.version_info[:3]) root.add_dependency(Dependency("poetry", version.text)) installer = Installer( self.io, env, root, NullLocker(self.data_dir.joinpath("poetry.lock"), {}), self.pool, Config(), installed=installed, ) installer.update(True) installer.dry_run(self.option("dry-run")) installer.run()
def test_accepts_fails_with_python_versions_mismatch() -> None: dependency = Dependency("A", "^1.0") dependency.python_versions = "^3.6" package = Package("B", "1.4") package.python_versions = "~3.5" assert not dependency.accepts(package)
def test_to_pep_508_caret() -> None: dependency = Dependency("foo", "^1.2.3") assert dependency.to_pep_508() == "foo (>=1.2.3,<2.0.0)" dependency = Dependency("foo", "^1.2") assert dependency.to_pep_508() == "foo (>=1.2,<2.0)" dependency = Dependency("foo", "^0.2.3") assert dependency.to_pep_508() == "foo (>=0.2.3,<0.3.0)" dependency = Dependency("foo", "^0.2") assert dependency.to_pep_508() == "foo (>=0.2,<0.3)"
def test_deprecation_warning(tester: CommandTester, repo: TestRepository) -> None: plugin = Package("poetry-plugin", "1.2.3") repo.add_package(Package("poetry", __version__)) repo.add_package(plugin) package = ProjectPackage("poetry-instance", __version__) package.add_dependency( Dependency(plugin.name, "^1.2.3", groups=[SelfCommand.ADDITIONAL_PACKAGE_GROUP])) content = Factory.create_pyproject_from_package(package) system_pyproject_file = SelfCommand.get_default_system_pyproject_file() system_pyproject_file.write_text(content.as_string(), encoding="utf-8") dependencies = get_self_command_dependencies(locked=False) assert "poetry-plugin" in dependencies tester.execute("poetry-plugin") assert (tester.io.fetch_error() == "This command is deprecated. Use self remove command instead.\n") dependencies = get_self_command_dependencies() assert "poetry-plugin" not in dependencies assert not dependencies
def test_to_pep_508_tilde() -> None: dependency = Dependency("foo", "~1.2.3") assert dependency.to_pep_508() == "foo (>=1.2.3,<1.3.0)" dependency = Dependency("foo", "~1.2") assert dependency.to_pep_508() == "foo (>=1.2,<1.3)" dependency = Dependency("foo", "~0.2.3") assert dependency.to_pep_508() == "foo (>=0.2.3,<0.3.0)" dependency = Dependency("foo", "~0.2") assert dependency.to_pep_508() == "foo (>=0.2,<0.3)"
def test_to_pep_508_in_extras() -> None: dependency = Dependency("Django", "^1.23") dependency.in_extras.append("foo") result = dependency.to_pep_508() assert result == 'Django (>=1.23,<2.0); extra == "foo"' result = dependency.to_pep_508(with_extras=False) assert result == "Django (>=1.23,<2.0)" dependency.in_extras.append("bar") result = dependency.to_pep_508() assert result == 'Django (>=1.23,<2.0); extra == "foo" or extra == "bar"' dependency.python_versions = "~2.7 || ^3.6" result = dependency.to_pep_508() assert (result == "Django (>=1.23,<2.0); " "(" 'python_version >= "2.7" and python_version < "2.8" ' 'or python_version >= "3.6" and python_version < "4.0"' ") " 'and (extra == "foo" or extra == "bar")') result = dependency.to_pep_508(with_extras=False) assert (result == "Django (>=1.23,<2.0); " 'python_version >= "2.7" and python_version < "2.8" ' 'or python_version >= "3.6" and python_version < "4.0"')
def solve(self) -> SolverResult: """ Finds a set of dependencies that match the root package's constraints, or raises an error if no such set is available. """ start = time.time() root_dependency = Dependency(self._root.name, self._root.version) root_dependency.is_root = True self._add_incompatibility( Incompatibility([Term(root_dependency, False)], RootCause())) try: next = self._root.name while next is not None: self._propagate(next) next = self._choose_package_version() return self._result() except Exception: raise finally: self._log("Version solving took {:.3f} seconds.\n" "Tried {} solutions.".format( time.time() - start, self._solution.attempted_solutions))
def handle(self) -> int: from poetry.__version__ import __version__ from poetry.core.packages.dependency import Dependency from poetry.core.semver.version import Version version = self.argument("version") if not version: version = ">=" + __version__ repo = self.pool.repositories[0] packages = repo.find_packages( Dependency("poetry", version, allows_prereleases=self.option("preview")) ) if not packages: self.line("No release found for the specified version") return 1 packages.sort( key=cmp_to_key( lambda x, y: 0 if x.version == y.version else int(x.version < y.version or -1) ) ) release = None for package in packages: if package.is_prerelease(): if self.option("preview"): release = package break continue release = package break if release is None: self.line("No new release found") return 1 if release.version == Version.parse(__version__): self.line("You are using the latest version") return 0 self.line("Updating <c1>Poetry</c1> to <c2>{}</c2>".format(release.version)) self.line("") self.update(release) self.line("") self.line( "<c1>Poetry</c1> (<c2>{}</c2>) is installed now. Great!".format( release.version ) ) return 0
def test_to_pep_508_with_patch_python_version(python_versions, marker): dependency = Dependency("Django", "^1.23") dependency.python_versions = python_versions expected = "Django (>=1.23,<2.0); {}".format(marker) assert expected == dependency.to_pep_508() assert marker == str(dependency.marker)
def test_marker_properly_unsets_python_constraint() -> None: dependency = Dependency("foo", "^1.2.3") dependency.marker = 'python_version >= "3.6"' # type: ignore[assignment] assert str(dependency.python_constraint) == ">=3.6" dependency.marker = "*" # type: ignore[assignment] assert str(dependency.python_constraint) == "*"
def test_it_cannot_solve_other_solver_errors(): from poetry.mixology.solutions.providers import PythonRequirementSolutionProvider incompatibility = Incompatibility([Term(Dependency("foo", "^1.0"), True)], NoVersionsCause()) exception = SolverProblemError(SolveFailure(incompatibility)) provider = PythonRequirementSolutionProvider() assert not provider.can_solve(exception)
def test_to_pep_508_with_patch_python_version(python_versions: str, marker: str) -> None: dependency = Dependency("Django", "^1.23") dependency.python_versions = python_versions expected = f"Django (>=1.23,<2.0); {marker}" assert dependency.to_pep_508() == expected assert str(dependency.marker) == marker
def get_dependency( name, constraint=None, category="main", optional=False, allows_prereleases=False ): return Dependency( name, constraint or "*", category=category, optional=optional, allows_prereleases=allows_prereleases, )
def test_get_package_information_chooses_correct_distribution(): repo = MockRepository() package = repo.package("isort", "4.3.4") assert package.name == "isort" assert package.version.text == "4.3.4" assert package.requires == [Dependency("futures", "*")] futures_dep = package.requires[0] assert futures_dep.python_versions == "~2.7"
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 test_single_page_repository_find_packages(): repo = MockSinglePageRepository("jax_releases") dep = Dependency("jaxlib", "0.3.7") packages = repo.find_packages(dep) assert len(packages) == 1 package = packages[0] assert package.name == dep.name assert package.to_dependency().to_pep_508() == dep.to_pep_508()
def convert_poetry_dependencies( dependencies: dict[str, str] | list[str]) -> list[str]: from poetry.core.packages.dependency import Dependency # type: ignore[import] if isinstance(dependencies, list): result = [] for dep in dependencies: match = re.match(r'\s*[\w\d\-\_]+', dep) if match and not dep.startswith('git+'): result.append( Dependency(match.group(0), dep[match.end():]).to_pep_508()) else: result.append(dep) return result elif isinstance(dependencies, dict): result = [] for key, version in dependencies.items(): if key == 'python': continue result.append(Dependency(key, version).to_pep_508()) return result else: raise TypeError(type(dependencies))
def test_dependency_group_remove_dependency() -> None: group = DependencyGroup(name="linter") group.add_dependency(Dependency(name="black", constraint="*")) group.add_dependency(Dependency(name="isort", constraint="*")) group.add_dependency(Dependency(name="flake8", constraint="*")) assert {dependency.name for dependency in group.dependencies} == { "black", "isort", "flake8", } group.remove_dependency("isort") assert {dependency.name for dependency in group.dependencies} == {"black", "flake8"} group.remove_dependency("black") assert {dependency.name for dependency in group.dependencies} == {"flake8"} group.remove_dependency("flake8") assert {dependency.name for dependency in group.dependencies} == set()
def handle(self) -> None: from poetry.__version__ import __version__ from poetry.core.packages.dependency import Dependency from poetry.core.semver.version import Version from poetry.repositories.pypi_repository import PyPiRepository self._check_recommended_installation() version = self.argument("version") if not version: version = ">=" + __version__ repo = PyPiRepository(fallback=False) packages = repo.find_packages( Dependency("poetry", version, allows_prereleases=self.option("preview")) ) if not packages: self.line("No release found for the specified version") return packages.sort( key=cmp_to_key( lambda x, y: 0 if x.version == y.version else int(x.version < y.version or -1) ) ) release = None for package in packages: if package.is_prerelease(): if self.option("preview"): release = package break continue release = package break if release is None: self.line("No new release found") return if release.version == Version.parse(__version__): self.line("You are using the latest version") return self.update(release)
def test_fallback_can_read_setup_to_get_dependencies(): repo = MockRepository(fallback=True) package = repo.package("sqlalchemy", "1.2.12") assert package.name == "sqlalchemy" assert len(package.requires) == 9 assert len([r for r in package.requires if r.is_optional()]) == 9 assert package.extras == { "mssql_pymssql": [Dependency("pymssql", "*")], "mssql_pyodbc": [Dependency("pyodbc", "*")], "mysql": [Dependency("mysqlclient", "*")], "oracle": [Dependency("cx_oracle", "*")], "postgresql": [Dependency("psycopg2", "*")], "postgresql_pg8000": [Dependency("pg8000", "*")], "postgresql_psycopg2binary": [Dependency("psycopg2-binary", "*")], "postgresql_psycopg2cffi": [Dependency("psycopg2cffi", "*")], "pymysql": [Dependency("pymysql", "*")], }