def test_solver_chooses_from_correct_repository_if_forced_and_transitive_dependency( package, installed, locked, io ): package.python_versions = "^3.7" package.add_dependency("foo", "^1.0") package.add_dependency("tomlkit", {"version": "^0.5", "source": "legacy"}) repo = Repository() foo = get_package("foo", "1.0.0") foo.add_dependency("tomlkit", "^0.5.0") repo.add_package(foo) pool = Pool([MockLegacyRepository(), repo, MockPyPIRepository()]) solver = Solver(package, pool, installed, locked, io) ops = solver.solve() check_solver_result( ops, [ {"job": "install", "package": get_package("tomlkit", "0.5.2")}, {"job": "install", "package": foo}, ], ) assert "legacy" == ops[0].package.source_type assert "http://foo.bar" == ops[0].package.source_url assert "" == ops[1].package.source_type assert "" == ops[1].package.source_url
def handle(self): from poetry.packages import Dependency from poetry.packages import ProjectPackage from poetry.puzzle import Solver from poetry.repositories.repository import Repository from poetry.semver import parse_constraint packages = self.argument("package") if not packages: package = self.poetry.package else: requirements = self._determine_requirements(packages) requirements = self._format_requirements(requirements) # validate requirements format for constraint in requirements.values(): parse_constraint(constraint) dependencies = [] for name, constraint in requirements.items(): dep = Dependency(name, constraint) extras = [] for extra in self.option("extras"): if " " in extra: extras += [e.strip() for e in extra.split(" ")] else: extras.append(extra) for ex in extras: dep.extras.append(ex) dependencies.append(dep) package = ProjectPackage(self.poetry.package.name, self.poetry.package.version) package.python_versions = (self.option("python") or self.poetry.package.python_versions) for dep in dependencies: package.requires.append(dep) solver = Solver(package, self.poetry.pool, Repository(), Repository(), self.output) ops = solver.solve() self.line("") self.line("Resolution results:") self.line("") for op in ops: package = op.package self.line(" - <info>{}</info> (<comment>{}</comment>)".format( package.name, package.version)) if package.requirements: for req_name, req_value in package.requirements.items(): self.line(" - {}: {}".format(req_name, req_value))
def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies( solver, repo, package ): package.python_versions = "~2.7 || ^3.4" package.add_dependency("A", {"version": "^1.0", "python": "^3.6"}) package.add_dependency("B", "^1.0") package_a = get_package("A", "1.0.0") package_a.python_versions = ">=3.6" package_a.marker = parse_marker( 'python_version >= "3.6" and python_version < "4.0"' ) package_b = get_package("B", "1.0.0") repo.add_package(package_a) repo.add_package(package_b) solver._locked = Repository([package_a]) ops = solver.solve(use_latest=[package_b.name]) check_solver_result( ops, [ {"job": "install", "package": package_a}, {"job": "install", "package": package_b}, ], )
def handle(self): from poetry.packages import Dependency from poetry.puzzle import Solver from poetry.repositories.repository import Repository from poetry.semver.version_parser import VersionParser packages = self.argument('package') if not packages: package = self.poetry.package dependencies = package.requires + package.dev_requires else: requirements = self._determine_requirements(packages) requirements = self._format_requirements(requirements) # validate requirements format parser = VersionParser() for constraint in requirements.values(): parser.parse_constraints(constraint) dependencies = [] for name, constraint in requirements.items(): dependencies.append(Dependency(name, constraint)) solver = Solver(self.poetry.package, self.poetry.pool, Repository(), Repository(), self.output) ops = solver.solve(dependencies) self.line('') self.line('Resolution results:') self.line('') for op in ops: package = op.package self.line(' - <info>{}</info> (<comment>{}</comment>)'.format( package.name, package.version))
def repository() -> Repository: return Repository()
def repo(): return Repository()
def locked(): return Repository()
def handle(self): from poetry.packages import ProjectPackage from poetry.puzzle import Solver from poetry.repositories.repository import Repository from poetry.semver import parse_constraint from poetry.utils.env import Env packages = self.argument("package") if not packages: package = self.poetry.package else: package = ProjectPackage(self.poetry.package.name, self.poetry.package.version) requirements = self._format_requirements(packages) for name, constraint in requirements.items(): dep = package.add_dependency(name, constraint) extras = [] for extra in self.option("extras"): if " " in extra: extras += [e.strip() for e in extra.split(" ")] else: extras.append(extra) for ex in extras: dep.extras.append(ex) package.python_versions = self.option("python") or ( self.poetry.package.python_versions) pool = self.poetry.pool solver = Solver(package, pool, Repository(), Repository(), self.output) ops = solver.solve() self.line("") self.line("Resolution results:") self.line("") if self.option("tree"): show_command = self.get_application().find("show") show_command.output = self.output show_command.init_styles() packages = [op.package for op in ops] repo = Repository(packages) requires = package.requires + package.dev_requires for pkg in repo.packages: for require in requires: if pkg.name == require.name: show_command.display_package_tree(pkg, repo) break return 0 env = Env.get() current_python_version = parse_constraint(".".join( str(v) for v in env.version_info)) for op in ops: pkg = op.package if self.option("install"): if not pkg.python_constraint.allows( current_python_version) or not env.is_valid_for_marker( pkg.marker): continue self.line(" - <info>{}</info> (<comment>{}</comment>)".format( pkg.name, pkg.version)) if not pkg.python_constraint.is_any(): self.line(" - python: {}".format(pkg.python_versions)) if not pkg.marker.is_any(): self.line(" - marker: {}".format(pkg.marker))
def solve_pypi( pip_specs: Dict[str, src_parser.Dependency], use_latest: List[str], pip_locked: Dict[str, src_parser.LockedDependency], conda_locked: Dict[str, src_parser.LockedDependency], python_version: str, platform: str, verbose: bool = False, ) -> Dict[str, src_parser.LockedDependency]: """ Solve pip dependencies for the given platform Parameters ---------- conda : Path to conda, mamba, or micromamba use_latest : Names of packages to update to the latest version compatible with pip_specs pip_specs : PEP440 package specifications pip_locked : Previous solution for the given platform (pip packages only) conda_locked : Current solution of conda-only specs for the given platform python_version : Version of Python in conda_locked platform : Target platform verbose : Print chatter from solver """ dummy_package = ProjectPackage("_dummy_package_", "0.0.0") dependencies = [get_dependency(spec) for spec in pip_specs.values()] for dep in dependencies: dummy_package.add_dependency(dep) pypi = PyPiRepository() pool = Pool(repositories=[pypi]) installed = Repository() locked = Repository() python_packages = dict() for dep in conda_locked.values(): if dep.name.startswith("__"): continue try: pypi_name = conda_name_to_pypi_name(dep.name).lower() except KeyError: continue # Prefer the Python package when its name collides with the Conda package # for the underlying library, e.g. python-xxhash (pypi: xxhash) over xxhash # (pypi: no equivalent) if pypi_name not in python_packages or pypi_name != dep.name: python_packages[pypi_name] = dep.version # treat conda packages as both locked and installed for name, version in python_packages.items(): for repo in (locked, installed): repo.add_package(Package(name=name, version=version)) # treat pip packages as locked only for spec in pip_locked.values(): locked.add_package(get_package(spec)) if verbose: io = ConsoleIO() io.set_verbosity(VERY_VERBOSE) else: io = NullIO() s = Solver( dummy_package, pool=pool, installed=installed, locked=locked, io=io, ) to_update = list({spec.name for spec in pip_locked.values() }.intersection(use_latest)) env = PlatformEnv(python_version, platform) # find platform-specific solution (e.g. dependencies conditioned on markers) with s.use_environment(env): result = s.solve(use_latest=to_update) chooser = Chooser(pool, env=env) # Extract distributions from Poetry package plan, ignoring uninstalls # (usually: conda package with no pypi equivalent) and skipped ops # (already installed) requirements: List[src_parser.LockedDependency] = [] for op in result: if not isinstance(op, Uninstall) and not op.skipped: # Take direct references verbatim source: Optional[src_parser.DependencySource] = None if op.package.source_type == "url": url, fragment = urldefrag(op.package.source_url) hash_type, hash = fragment.split("=") hash = src_parser.HashModel(**{hash_type: hash}) source = src_parser.DependencySource(type="url", url=op.package.source_url) # Choose the most specific distribution for the target else: link = chooser.choose_for(op.package) url = link.url_without_fragment hash = src_parser.HashModel(**{link.hash_name: link.hash}) requirements.append( src_parser.LockedDependency( name=op.package.name, version=str(op.package.version), manager="pip", source=source, platform=platform, dependencies={ dep.name: str(dep.constraint) for dep in op.package.requires }, url=url, hash=hash, )) # use PyPI names of conda packages to walking the dependency tree and propagate # categories from explicit to transitive dependencies planned = { **{dep.name: dep for dep in requirements}, # prefer conda packages so add them afterwards } for conda_name, dep in conda_locked.items(): try: pypi_name = conda_name_to_pypi_name(conda_name).lower() except KeyError: # no conda-name found, assuming conda packages do NOT intersect with the pip package continue planned[pypi_name] = dep src_parser._apply_categories(requested=pip_specs, planned=planned) return {dep.name: dep for dep in requirements}
def handle(self): from clikit.utils.terminal import Terminal from poetry.io.null_io import NullIO from poetry.puzzle.solver import Solver from poetry.repositories.installed_repository import InstalledRepository from poetry.repositories.pool import Pool from poetry.repositories.repository import Repository from poetry.utils.helpers import get_package_version_display_string package = self.argument("package") if self.option("tree"): self.init_styles(self.io) if self.option("outdated"): self._args.set_option("latest", True) include_dev = not self.option("no-dev") locked_repo = self.poetry.locker.locked_repository(True) # Show tree view if requested if self.option("tree") and not package: requires = self.poetry.package.requires + self.poetry.package.dev_requires packages = locked_repo.packages for package in packages: for require in requires: if package.name == require.name: self.display_package_tree(self._io, package, locked_repo) break return 0 table = self.table(style="compact") # table.style.line_vc_char = "" locked_packages = locked_repo.packages pool = Pool(ignore_repository_names=True) pool.add_repository(locked_repo) solver = Solver( self.poetry.package, pool=pool, installed=Repository(), locked=locked_repo, io=NullIO(), ) solver.provider.load_deferred(False) with solver.use_environment(self.env): ops = solver.solve() required_locked_packages = set( [op.package for op in ops if not op.skipped]) if self.option("no-dev"): required_locked_packages = [ p for p in locked_packages if p.category == "main" ] if package: pkg = None for locked in locked_packages: if package.lower() == locked.name: pkg = locked break if not pkg: raise ValueError("Package {} not found".format(package)) if self.option("tree"): self.display_package_tree(self.io, pkg, locked_repo) return 0 rows = [ ["<info>name</>", " : <c1>{}</>".format(pkg.pretty_name)], [ "<info>version</>", " : <b>{}</b>".format(pkg.pretty_version) ], ["<info>description</>", " : {}".format(pkg.description)], ] table.add_rows(rows) table.render(self.io) if pkg.requires: self.line("") self.line("<info>dependencies</info>") for dependency in pkg.requires: self.line(" - <c1>{}</c1> <b>{}</b>".format( dependency.pretty_name, dependency.pretty_constraint)) return 0 show_latest = self.option("latest") show_all = self.option("all") terminal = Terminal() width = terminal.width name_length = version_length = latest_length = 0 latest_packages = {} latest_statuses = {} installed_repo = InstalledRepository.load(self.env) # Computing widths for locked in locked_packages: if locked not in required_locked_packages and not show_all: continue current_length = len(locked.pretty_name) if not self._io.output.supports_ansi(): installed_status = self.get_installed_status( locked, installed_repo) if installed_status == "not-installed": current_length += 4 if show_latest: latest = self.find_latest_package(locked, include_dev) if not latest: latest = locked latest_packages[locked.pretty_name] = latest update_status = latest_statuses[ locked.pretty_name] = self.get_update_status( latest, locked) if not self.option( "outdated") or update_status != "up-to-date": name_length = max(name_length, current_length) version_length = max( version_length, len( get_package_version_display_string( locked, root=self.poetry.file.parent)), ) latest_length = max( latest_length, len( get_package_version_display_string( latest, root=self.poetry.file.parent)), ) else: name_length = max(name_length, current_length) version_length = max( version_length, len( get_package_version_display_string( locked, root=self.poetry.file.parent)), ) write_version = name_length + version_length + 3 <= width write_latest = name_length + version_length + latest_length + 3 <= width write_description = name_length + version_length + latest_length + 24 <= width for locked in locked_packages: color = "cyan" name = locked.pretty_name install_marker = "" if locked not in required_locked_packages: if not show_all: continue color = "black;options=bold" else: installed_status = self.get_installed_status( locked, installed_repo) if installed_status == "not-installed": color = "red" if not self._io.output.supports_ansi(): # Non installed in non decorated mode install_marker = " (!)" if (show_latest and self.option("outdated") and latest_statuses[locked.pretty_name] == "up-to-date"): continue line = "<fg={}>{:{}}{}</>".format( color, name, name_length - len(install_marker), install_marker) if write_version: line += " <b>{:{}}</b>".format( get_package_version_display_string( locked, root=self.poetry.file.parent), version_length, ) if show_latest: latest = latest_packages[locked.pretty_name] update_status = latest_statuses[locked.pretty_name] if write_latest: color = "green" if update_status == "semver-safe-update": color = "red" elif update_status == "update-possible": color = "yellow" line += " <fg={}>{:{}}</>".format( color, get_package_version_display_string( latest, root=self.poetry.file.parent), latest_length, ) if write_description: description = locked.description remaining = width - name_length - version_length - 4 if show_latest: remaining -= latest_length if len(locked.description) > remaining: description = description[:remaining - 3] + "..." line += " " + description self.line(line)
def test_self_update_does_not_update_non_recommended_installation( tester: CommandTester, http: type[httpretty.httpretty], mocker: MockerFixture, environ: None, tmp_venv: VirtualEnv, ): mocker.patch.object(EnvManager, "get_system_env", return_value=tmp_venv) command = tester.command new_version = Version.parse(__version__).next_minor().text old_poetry = Package("poetry", __version__) old_poetry.add_dependency(Factory.create_dependency("cleo", "^0.8.2")) new_poetry = Package("poetry", new_version) new_poetry.add_dependency(Factory.create_dependency("cleo", "^1.0.0")) installed_repository = Repository() installed_repository.add_package(old_poetry) installed_repository.add_package(Package("cleo", "0.8.2")) repository = Repository() repository.add_package(new_poetry) repository.add_package(Package("cleo", "1.0.0")) pool = Pool() pool.add_repository(repository) command._pool = pool with pytest.raises(PoetrySimpleConsoleException): tester.execute()
def test_self_update_can_update_from_recommended_installation( tester: CommandTester, http: type[httpretty.httpretty], mocker: MockerFixture, environ: None, tmp_venv: VirtualEnv, ): mocker.patch.object(EnvManager, "get_system_env", return_value=tmp_venv) command = tester.command command._data_dir = tmp_venv.path.parent new_version = Version.parse(__version__).next_minor().text old_poetry = Package("poetry", __version__) old_poetry.add_dependency(Factory.create_dependency("cleo", "^0.8.2")) new_poetry = Package("poetry", new_version) new_poetry.add_dependency(Factory.create_dependency("cleo", "^1.0.0")) installed_repository = Repository() installed_repository.add_package(old_poetry) installed_repository.add_package(Package("cleo", "0.8.2")) repository = Repository() repository.add_package(new_poetry) repository.add_package(Package("cleo", "1.0.0")) pool = Pool() pool.add_repository(repository) command._pool = pool mocker.patch.object(InstalledRepository, "load", return_value=installed_repository) tester.execute() expected_output = f"""\ Updating Poetry to 1.2.0 Updating dependencies Resolving dependencies... Package operations: 0 installs, 2 updates, 0 removals - Updating cleo (0.8.2 -> 1.0.0) - Updating poetry ({__version__} -> {new_version}) Updating the poetry script Poetry ({new_version}) is installed now. Great! """ assert tester.io.fetch_output() == expected_output
def handle(self) -> int: from cleo.io.null_io import NullIO from poetry.core.packages.project_package import ProjectPackage from poetry.factory import Factory from poetry.puzzle.solver import Solver from poetry.repositories.pool import Pool from poetry.repositories.repository import Repository from poetry.utils.env import EnvManager packages = self.argument("package") if not packages: package = self.poetry.package else: # Using current pool for determine_requirements() self._pool = self.poetry.pool package = ProjectPackage(self.poetry.package.name, self.poetry.package.version) # Silencing output verbosity = self.io.output.verbosity self.io.output.set_verbosity(Verbosity.QUIET) requirements = self._determine_requirements(packages) self.io.output.set_verbosity(verbosity) for constraint in requirements: name = constraint.pop("name") assert isinstance(name, str) extras = [] for extra in self.option("extras"): if " " in extra: extras += [e.strip() for e in extra.split(" ")] else: extras.append(extra) constraint["extras"] = extras package.add_dependency( Factory.create_dependency(name, constraint)) package.python_versions = self.option("python") or ( self.poetry.package.python_versions) pool = self.poetry.pool solver = Solver(package, pool, Repository(), Repository(), self._io) ops = solver.solve().calculate_operations() self.line("") self.line("Resolution results:") self.line("") if self.option("tree"): show_command: ShowCommand = self.application.find("show") show_command.init_styles(self.io) packages = [op.package for op in ops] repo = Repository(packages=packages) requires = package.all_requires for pkg in repo.packages: for require in requires: if pkg.name == require.name: show_command.display_package_tree(self.io, pkg, repo) break return 0 table = self.table(style="compact") table.style.set_vertical_border_chars("", " ") rows = [] if self.option("install"): env = EnvManager(self.poetry).get() pool = Pool() locked_repository = Repository() for op in ops: locked_repository.add_package(op.package) pool.add_repository(locked_repository) solver = Solver(package, pool, Repository(), Repository(), NullIO()) with solver.use_environment(env): ops = solver.solve().calculate_operations() for op in ops: if self.option("install") and op.skipped: continue pkg = op.package row = [ f"<c1>{pkg.complete_name}</c1>", f"<b>{pkg.version}</b>", ] if not pkg.marker.is_any(): row[2] = str(pkg.marker) rows.append(row) table.set_rows(rows) table.render() return 0
def handle(self) -> int | None: from cleo.io.null_io import NullIO from cleo.terminal import Terminal from poetry.puzzle.solver import Solver from poetry.repositories.installed_repository import InstalledRepository from poetry.repositories.pool import Pool from poetry.repositories.repository import Repository from poetry.utils.helpers import get_package_version_display_string package = self.argument("package") if self.option("tree"): self.init_styles(self.io) if self.option("why"): if self.option("tree") and package is None: self.line_error( "<error>Error: --why requires a package when combined with" " --tree.</error>" ) return 1 if not self.option("tree") and package: self.line_error( "<error>Error: --why cannot be used without --tree when displaying" " a single package.</error>" ) return 1 if self.option("outdated"): self._io.input.set_option("latest", True) if not self.poetry.locker.is_locked(): self.line_error( "<error>Error: poetry.lock not found. Run `poetry lock` to create" " it.</error>" ) return 1 locked_repo = self.poetry.locker.locked_repository() root = self.project_with_activated_groups_only() # Show tree view if requested if self.option("tree") and package is None: requires = root.all_requires packages = locked_repo.packages for p in packages: for require in requires: if p.name == require.name: self.display_package_tree(self._io, p, locked_repo) break return 0 table = self.table(style="compact") locked_packages = locked_repo.packages pool = Pool(ignore_repository_names=True) pool.add_repository(locked_repo) solver = Solver( root, pool=pool, installed=Repository(), locked=locked_repo, io=NullIO(), ) solver.provider.load_deferred(False) with solver.use_environment(self.env): ops = solver.solve().calculate_operations() required_locked_packages = {op.package for op in ops if not op.skipped} if package: pkg = None for locked in locked_packages: if package.lower() == locked.name: pkg = locked break if not pkg: raise ValueError(f"Package {package} not found") required_by = reverse_deps(pkg, locked_repo) if self.option("tree"): if self.option("why"): # The default case if there's no reverse dependencies is to query # the subtree for pkg but if any rev-deps exist we'll query for each # of them in turn packages = [pkg] if required_by: packages = [ p for p in locked_packages for r in required_by.keys() if p.name == r ] else: # if no rev-deps exist we'll make this clear as it can otherwise # look very odd for packages that also have no or few direct # dependencies self._io.write_line( f"Package {package} is a direct dependency." ) for p in packages: self.display_package_tree( self._io, p, locked_repo, why_package=pkg ) else: self.display_package_tree(self._io, pkg, locked_repo) return 0 rows = [ ["<info>name</>", f" : <c1>{pkg.pretty_name}</>"], ["<info>version</>", f" : <b>{pkg.pretty_version}</b>"], ["<info>description</>", f" : {pkg.description}"], ] table.add_rows(rows) table.render() if pkg.requires: self.line("") self.line("<info>dependencies</info>") for dependency in pkg.requires: self.line( f" - <c1>{dependency.pretty_name}</c1>" f" <b>{dependency.pretty_constraint}</b>" ) if required_by: self.line("") self.line("<info>required by</info>") for parent, requires_version in required_by.items(): self.line(f" - <c1>{parent}</c1> <b>{requires_version}</b>") return 0 show_latest = self.option("latest") show_all = self.option("all") terminal = Terminal() width = terminal.width name_length = version_length = latest_length = required_by_length = 0 latest_packages = {} latest_statuses = {} installed_repo = InstalledRepository.load(self.env) # Computing widths for locked in locked_packages: if locked not in required_locked_packages and not show_all: continue current_length = len(locked.pretty_name) if not self._io.output.is_decorated(): installed_status = self.get_installed_status(locked, installed_repo) if installed_status == "not-installed": current_length += 4 if show_latest: latest = self.find_latest_package(locked, root) if not latest: latest = locked latest_packages[locked.pretty_name] = latest update_status = latest_statuses[ locked.pretty_name ] = self.get_update_status(latest, locked) if not self.option("outdated") or update_status != "up-to-date": name_length = max(name_length, current_length) version_length = max( version_length, len( get_package_version_display_string( locked, root=self.poetry.file.parent ) ), ) latest_length = max( latest_length, len( get_package_version_display_string( latest, root=self.poetry.file.parent ) ), ) if self.option("why"): required_by = reverse_deps(locked, locked_repo) required_by_length = max( required_by_length, len(" from " + ",".join(required_by.keys())), ) else: name_length = max(name_length, current_length) version_length = max( version_length, len( get_package_version_display_string( locked, root=self.poetry.file.parent ) ), ) if self.option("why"): required_by = reverse_deps(locked, locked_repo) required_by_length = max( required_by_length, len(" from " + ",".join(required_by.keys())) ) write_version = name_length + version_length + 3 <= width write_latest = name_length + version_length + latest_length + 3 <= width why_end_column = ( name_length + version_length + latest_length + required_by_length ) write_why = self.option("why") and (why_end_column + 3) <= width write_description = (why_end_column + 24) <= width for locked in locked_packages: color = "cyan" name = locked.pretty_name install_marker = "" if locked not in required_locked_packages: if not show_all: continue color = "black;options=bold" else: installed_status = self.get_installed_status(locked, installed_repo) if installed_status == "not-installed": color = "red" if not self._io.output.is_decorated(): # Non installed in non decorated mode install_marker = " (!)" if ( show_latest and self.option("outdated") and latest_statuses[locked.pretty_name] == "up-to-date" ): continue line = ( f"<fg={color}>" f"{name:{name_length - len(install_marker)}}{install_marker}</>" ) if write_version: version = get_package_version_display_string( locked, root=self.poetry.file.parent ) line += f" <b>{version:{version_length}}</b>" if show_latest: latest = latest_packages[locked.pretty_name] update_status = latest_statuses[locked.pretty_name] if write_latest: color = "green" if update_status == "semver-safe-update": color = "red" elif update_status == "update-possible": color = "yellow" version = get_package_version_display_string( latest, root=self.poetry.file.parent ) line += f" <fg={color}>{version:{latest_length}}</>" if write_why: required_by = reverse_deps(locked, locked_repo) if required_by: content = ",".join(required_by.keys()) # subtract 6 for ' from ' line += f" from {content:{required_by_length - 6}}" else: line += " " * required_by_length if write_description: description = locked.description remaining = ( width - name_length - version_length - required_by_length - 4 ) if show_latest: remaining -= latest_length if len(locked.description) > remaining: description = description[: remaining - 3] + "..." line += " " + description self.line(line) return None
def _patch_repos(repo: TestRepository, installed: Repository) -> None: poetry = Package("poetry", __version__) repo.add_package(poetry) installed.add_package(poetry)
def handle(self): from poetry.core.packages.project_package import ProjectPackage from poetry.io.null_io import NullIO from poetry.puzzle import Solver from poetry.repositories.pool import Pool from poetry.repositories.repository import Repository from poetry.utils.env import EnvManager packages = self.argument("package") if not packages: package = self.poetry.package else: # Using current pool for determine_requirements() self._pool = self.poetry.pool package = ProjectPackage( self.poetry.package.name, self.poetry.package.version ) # Silencing output is_quiet = self.io.output.is_quiet() if not is_quiet: self.io.output.set_quiet(True) requirements = self._determine_requirements(packages) if not is_quiet: self.io.output.set_quiet(False) for constraint in requirements: name = constraint.pop("name") dep = package.add_dependency(name, constraint) extras = [] for extra in self.option("extras"): if " " in extra: extras += [e.strip() for e in extra.split(" ")] else: extras.append(extra) for ex in extras: dep.extras.append(ex) package.python_versions = self.option("python") or ( self.poetry.package.python_versions ) pool = self.poetry.pool solver = Solver(package, pool, Repository(), Repository(), self._io) ops = solver.solve() self.line("") self.line("Resolution results:") self.line("") if self.option("tree"): show_command = self.application.find("show") show_command.init_styles(self.io) packages = [op.package for op in ops] repo = Repository(packages) requires = package.requires + package.dev_requires for pkg in repo.packages: for require in requires: if pkg.name == require.name: show_command.display_package_tree(self.io, pkg, repo) break return 0 table = self.table([], style="borderless") rows = [] if self.option("install"): env = EnvManager(self.poetry).get() pool = Pool() locked_repository = Repository() for op in ops: locked_repository.add_package(op.package) pool.add_repository(locked_repository) solver = Solver(package, pool, Repository(), Repository(), NullIO()) with solver.use_environment(env): ops = solver.solve() for op in ops: if self.option("install") and op.skipped: continue pkg = op.package row = [ "<c1>{}</c1>".format(pkg.name), "<b>{}</b>".format(pkg.version), "", ] if not pkg.marker.is_any(): row[2] = str(pkg.marker) rows.append(row) table.set_rows(rows) table.render(self.io)
def handle(self): from poetry.packages import ProjectPackage from poetry.puzzle import Solver from poetry.repositories.repository import Repository from poetry.semver import parse_constraint from poetry.utils.env import EnvManager packages = self.argument("package") if not packages: package = self.poetry.package else: # Using current pool for determine_requirements() self._pool = self.poetry.pool package = ProjectPackage(self.poetry.package.name, self.poetry.package.version) # Silencing output is_quiet = self.io.output.is_quiet() if not is_quiet: self.io.output.set_quiet(True) requirements = self._determine_requirements(packages) if not is_quiet: self.io.output.set_quiet(False) for constraint in requirements: name = constraint.pop("name") dep = package.add_dependency(name, constraint) extras = [] for extra in self.option("extras"): if " " in extra: extras += [e.strip() for e in extra.split(" ")] else: extras.append(extra) for ex in extras: dep.extras.append(ex) package.python_versions = self.option("python") or ( self.poetry.package.python_versions) pool = self.poetry.pool solver = Solver(package, pool, Repository(), Repository(), self._io) ops = solver.solve() self.line("") self.line("Resolution results:") self.line("") if self.option("tree"): show_command = self.application.find("show") show_command.init_styles(self.io) packages = [op.package for op in ops] repo = Repository(packages) requires = package.requires + package.dev_requires for pkg in repo.packages: for require in requires: if pkg.name == require.name: show_command.display_package_tree(self.io, pkg, repo) break return 0 env = EnvManager(self.poetry.config).get(self.poetry.file.parent) current_python_version = parse_constraint(".".join( str(v) for v in env.version_info)) table = self.table([], style="borderless") rows = [] for op in ops: pkg = op.package if self.option("install"): if not pkg.python_constraint.allows( current_python_version) or not env.is_valid_for_marker( pkg.marker): continue row = [ "<info>{}</info>".format(pkg.name), "<b>{}</b>".format(pkg.version), "", ] if not pkg.marker.is_any(): row[2] = str(pkg.marker) rows.append(row) table.set_rows(rows) table.render(self.io)