Пример #1
0
    def _update_with_new_method(self, version):
        from poetry.config.config import Config
        from poetry.core.packages.dependency import Dependency
        from poetry.core.packages.project_package import ProjectPackage
        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.run()
Пример #2
0
def test_builder_setup_generation_runs_with_pip_editable(tmp_dir: str):
    # create an isolated copy of the project
    fixture = Path(
        __file__).parent.parent.parent / "fixtures" / "extended_project"
    extended_project = Path(tmp_dir) / "extended_project"

    shutil.copytree(fixture, extended_project)
    assert extended_project.exists()

    poetry = Factory().create_poetry(extended_project)

    # we need a venv with setuptools since we are verifying setup.py builds
    with ephemeral_environment(flags={"no-setuptools": False}) as venv:
        builder = EditableBuilder(poetry, venv, NullIO())
        builder.build()

        # is the package installed?
        repository = InstalledRepository.load(venv)
        assert repository.package("extended-project", "1.2.3")

        # check for the module built by build.py
        try:
            output = venv.run_python_script(
                "from extended_project import built; print(built.__file__)"
            ).strip()
        except EnvCommandError:
            pytest.fail("Unable to import built module")
        else:
            built_py = Path(output).resolve()

        expected = extended_project / "extended_project" / "built.py"

        # ensure the package was installed as editable
        assert built_py == expected.resolve()
Пример #3
0
    def _get_operations_from_lock(
            self, locked_repository: Repository) -> List[Operation]:
        installed_repo = InstalledRepository.load(self._venv)
        ops = []

        extra_packages = [
            p.name for p in self._get_extra_packages(locked_repository)
        ]
        for locked in locked_repository.packages:
            is_installed = False
            for installed in installed_repo.packages:
                if locked.name == installed.name:
                    is_installed = True
                    if locked.category == 'dev' and not self.is_dev_mode():
                        ops.append(Uninstall(locked))
                    elif locked.optional and locked.name not in extra_packages:
                        # Installed but optional and not requested in extras
                        ops.append(Uninstall(locked))
                    elif locked.version != installed.version:
                        ops.append(Update(installed, locked))

            if not is_installed:
                # If it's optional and not in required extras
                # we do not install
                if locked.optional and locked.name not in extra_packages:
                    continue

                ops.append(Install(locked))

        return ops
Пример #4
0
def repository(mocker,
               env):  # type: (MockFixture, MockEnv) -> InstalledRepository
    mocker.patch(
        "poetry.utils._compat.metadata.Distribution.discover",
        return_value=INSTALLED_RESULTS,
    )
    mocker.patch(
        "poetry.core.vcs.git.Git.rev_parse",
        return_value="bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6",
    )
    mocker.patch(
        "poetry.core.vcs.git.Git.remote_urls",
        side_effect=[
            {
                "remote.origin.url":
                "https://github.com/sdispater/pendulum.git"
            },
            {
                "remote.origin.url": "[email protected]:sdispater/pendulum.git"
            },
        ],
    )
    mocker.patch("poetry.repositories.installed_repository._VENDORS",
                 str(VENDOR_DIR))
    return InstalledRepository.load(env)
Пример #5
0
def test_load(mocker):
    mocker.patch(
        "importlib_metadata.Distribution.discover", return_value=INSTALLED_RESULTS
    )
    mocker.patch(
        "poetry.vcs.git.Git.rev_parse",
        return_value="bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6",
    )
    mocker.patch(
        "poetry.vcs.git.Git.remote_urls",
        side_effect=[
            {"remote.origin.url": "https://github.com/sdispater/pendulum.git"},
            {"remote.origin.url": "[email protected]:sdispater/pendulum.git"},
        ],
    )
    repository = InstalledRepository.load(MockEnv(path=ENV_DIR))

    assert len(repository.packages) == 2

    cleo = repository.packages[0]
    assert cleo.name == "cleo"
    assert cleo.version.text == "0.7.6"
    assert (
        cleo.description
        == "Cleo allows you to create beautiful and testable command-line interfaces."
    )

    pendulum = repository.packages[1]
    assert pendulum.name == "pendulum"
    assert pendulum.version.text == "2.0.5"
    assert pendulum.description == "Python datetimes made easy"
    assert pendulum.source_type == "git"
    assert pendulum.source_url == "https://github.com/sdispater/pendulum.git"
    assert pendulum.source_reference == "bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6"
Пример #6
0
def installed():
    original = InstalledRepository.load
    InstalledRepository.load = lambda _: InstalledRepository()

    yield

    InstalledRepository.load = original
Пример #7
0
    def _get_operations_from_lock(
            self, locked_repository: Repository) -> List[Operation]:
        installed_repo = InstalledRepository.load(self._io.venv)
        ops = []
        extras = []
        for extra_name, packages in self._locker.lock_data.get(
                'extras').items():
            if extra_name in self._extras:
                for package in packages:
                    extras.append(package.lower())

        for locked in locked_repository.packages:
            is_installed = False
            for installed in installed_repo.packages:
                if locked.name == installed.name:
                    is_installed = True
                    if locked.category == 'dev' and not self.is_dev_mode():
                        ops.append(Uninstall(locked))
                    elif locked.is_optional() and locked.name not in extras:
                        # Installed but optional and not requested in extras
                        ops.append(Uninstall(locked))
                    elif locked.version != installed.version:
                        ops.append(Update(installed, locked))

            if not is_installed:
                # If it's optional and not in required extras
                # we do not install
                if locked.is_optional() and locked.name not in extras:
                    continue

                ops.append(Install(locked))

        return ops
def test_load():
    repository = InstalledRepository.load(MockEnv())

    assert len(repository.packages) == 2

    cleo = repository.packages[0]
    assert cleo.name == "cleo"
    assert cleo.version.text == "0.6.8"

    pendulum = repository.packages[1]
    assert pendulum.name == "pendulum"
    assert pendulum.version.text == "0.0.0"
    assert pendulum.source_type == "git"
    assert pendulum.source_url == "https://github.com/sdispater/pendulum.git"
    assert pendulum.source_reference == "bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6"
Пример #9
0
def repository(mocker: MockerFixture, env: MockEnv) -> InstalledRepository:
    mocker.patch(
        "poetry.utils._compat.metadata.Distribution.discover",
        return_value=INSTALLED_RESULTS,
    )
    mocker.patch(
        "poetry.vcs.git.Git.info",
        return_value=namedtuple("GitRepoLocalInfo", "origin revision")(
            origin="https://github.com/sdispater/pendulum.git",
            revision="bb058f6b78b2d28ef5d9a5e759cfa179a1a713d6",
        ),
    )
    mocker.patch("poetry.repositories.installed_repository._VENDORS",
                 str(VENDOR_DIR))
    return InstalledRepository.load(env)
Пример #10
0
def test_env_no_pip(tmp_path: Path, poetry: Poetry, flags: dict[str, bool],
                    packages: set[str]):
    venv_path = tmp_path / "venv"
    EnvManager(poetry).build_venv(path=venv_path, flags=flags)
    env = VirtualEnv(venv_path)
    installed_repository = InstalledRepository.load(env=env,
                                                    with_dependencies=True)
    installed_packages = {
        package.name
        for package in installed_repository.packages
        # workaround for BSD test environments
        if package.name != "sqlite3"
    }

    assert installed_packages == packages
Пример #11
0
def test_load_successful_with_invalid_distribution(
    caplog: LogCaptureFixture, mocker: MockerFixture, env: MockEnv, tmp_dir: str
) -> None:
    invalid_dist_info = Path(tmp_dir) / "site-packages" / "invalid-0.1.0.dist-info"
    invalid_dist_info.mkdir(parents=True)
    mocker.patch(
        "poetry.utils._compat.metadata.Distribution.discover",
        return_value=INSTALLED_RESULTS + [metadata.PathDistribution(invalid_dist_info)],
    )
    repository_with_invalid_distribution = InstalledRepository.load(env)

    assert (
        len(repository_with_invalid_distribution.packages) == len(INSTALLED_RESULTS) - 1
    )
    assert len(caplog.messages) == 1

    message = caplog.messages[0]
    assert message.startswith("Project environment contains an invalid distribution")
    assert str(invalid_dist_info) in message
Пример #12
0
    def handle(self) -> Optional[int]:
        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("outdated"):
            self._io.input.set_option("latest", True)

        excluded_groups = []
        included_groups = []
        only_groups = []
        if self.option("no-dev"):
            self.line_error(
                "<warning>The `<fg=yellow;options=bold>--no-dev</>` option is"
                " deprecated, use the `<fg=yellow;options=bold>--without dev</>`"
                " notation instead.</warning>"
            )
            excluded_groups.append("dev")

        excluded_groups.extend(
            [
                group.strip()
                for groups in self.option("without")
                for group in groups.split(",")
            ]
        )
        included_groups.extend(
            [
                group.strip()
                for groups in self.option("with")
                for group in groups.split(",")
            ]
        )
        only_groups.extend(
            [
                group.strip()
                for groups in self.option("only")
                for group in groups.split(",")
            ]
        )

        if self.option("default"):
            only_groups.append("default")

        locked_repo = self.poetry.locker.locked_repository(True)

        if only_groups:
            root = self.poetry.package.with_dependency_groups(only_groups, only=True)
        else:
            root = self.poetry.package.with_dependency_groups(
                included_groups
            ).without_dependency_groups(excluded_groups)

        # Show tree view if requested
        if self.option("tree") and not package:
            requires = root.all_requires
            packages = locked_repo.packages
            for pkg in packages:
                for require in requires:
                    if pkg.name == require.name:
                        self.display_package_tree(self._io, pkg, 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")

            if self.option("tree"):
                self.display_package_tree(self.io, pkg, locked_repo)

                return 0

            required_by = {}
            for locked in locked_packages:
                dependencies = {d.name: d.pretty_constraint for d in locked.requires}

                if pkg.name in dependencies:
                    required_by[locked.pretty_name] = dependencies[pkg.name]

            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 = 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
                            )
                        ),
                    )
            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.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_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)
        return None
Пример #13
0
    def handle(self) -> int:
        from pathlib import Path

        import tomlkit

        from cleo.io.inputs.string_input import StringInput
        from cleo.io.io import IO
        from poetry.core.pyproject.toml import PyProjectTOML
        from poetry.core.semver.helpers import parse_constraint

        from poetry.factory import Factory
        from poetry.packages.project_package import ProjectPackage
        from poetry.repositories.installed_repository import InstalledRepository
        from poetry.utils.env import EnvManager

        plugins = self.argument("plugins")

        # Plugins should be installed in the system env to be globally available
        system_env = EnvManager.get_system_env(naive=True)

        env_dir = Path(os.getenv("POETRY_HOME") or system_env.path)

        # We check for the plugins existence first.
        if env_dir.joinpath("pyproject.toml").exists():
            pyproject = tomlkit.loads(
                env_dir.joinpath("pyproject.toml").read_text(encoding="utf-8"))
            poetry_content = pyproject["tool"]["poetry"]
            existing_packages = self.get_existing_packages_from_input(
                plugins, poetry_content, "dependencies")

            if existing_packages:
                self.notify_about_existing_packages(existing_packages)

            plugins = [
                plugin for plugin in plugins if plugin not in existing_packages
            ]

        if not plugins:
            return 0

        plugins = self._determine_requirements(plugins)

        # We retrieve the packages installed in the system environment.
        # We assume that this environment will be a self contained virtual environment
        # built by the official installer or by pipx.
        # If not, it might lead to side effects since other installed packages
        # might not be required by Poetry but still taken into account when resolving dependencies.
        installed_repository = InstalledRepository.load(system_env,
                                                        with_dependencies=True)

        root_package = None
        for package in installed_repository.packages:
            if package.name == "poetry":
                root_package = ProjectPackage(package.name, package.version)
                for dependency in package.requires:
                    root_package.add_dependency(dependency)

                break

        root_package.python_versions = ".".join(
            str(v) for v in system_env.version_info[:3])
        # We create a `pyproject.toml` file based on all the information
        # we have about the current environment.
        if not env_dir.joinpath("pyproject.toml").exists():
            Factory.create_pyproject_from_package(root_package, env_dir)

        # We add the plugins to the dependencies section of the previously
        # created `pyproject.toml` file
        pyproject = PyProjectTOML(env_dir.joinpath("pyproject.toml"))
        poetry_content = pyproject.poetry_config
        poetry_dependency_section = poetry_content["dependencies"]
        plugin_names = []
        for plugin in plugins:
            if "version" in plugin:
                # Validate version constraint
                parse_constraint(plugin["version"])

            constraint = tomlkit.inline_table()
            for name, value in plugin.items():
                if name == "name":
                    continue

                constraint[name] = value

            if len(constraint) == 1 and "version" in constraint:
                constraint = constraint["version"]

            poetry_dependency_section[plugin["name"]] = constraint
            plugin_names.append(plugin["name"])

        pyproject.save()

        # From this point forward, all the logic will be deferred to
        # the update command, by using the previously created `pyproject.toml`
        # file.
        application = cast(Application, self.application)
        update_command: UpdateCommand = cast(UpdateCommand,
                                             application.find("update"))
        # We won't go through the event dispatching done by the application
        # so we need to configure the command manually
        update_command.set_poetry(Factory().create_poetry(env_dir))
        update_command.set_env(system_env)
        application._configure_installer(update_command, self._io)

        argv = ["update"] + plugin_names
        if self.option("dry-run"):
            argv.append("--dry-run")

        return update_command.run(
            IO(
                StringInput(" ".join(argv)),
                self._io.output,
                self._io.error_output,
            ))
Пример #14
0
 def _get_installed(self) -> InstalledRepository:
     return InstalledRepository.load(self._env)
Пример #15
0
    def handle(self) -> int:
        from poetry.plugins.application_plugin import ApplicationPlugin
        from poetry.plugins.plugin_manager import PluginManager
        from poetry.repositories.installed_repository import InstalledRepository
        from poetry.utils.env import EnvManager
        from poetry.utils.helpers import canonicalize_name

        plugins: DefaultDict[str, Dict[str, Union[
            "Package", List[str]]]] = defaultdict(lambda: {
                "package": None,
                "plugins": [],
                "application_plugins": [],
            })

        entry_points = (
            PluginManager("application.plugin").get_plugin_entry_points() +
            PluginManager("plugin").get_plugin_entry_points())

        system_env = EnvManager.get_system_env(naive=True)
        installed_repository = InstalledRepository.load(system_env,
                                                        with_dependencies=True)

        packages_by_name = {
            pkg.name: pkg
            for pkg in installed_repository.packages
        }

        for entry_point in entry_points:
            plugin = entry_point.load()
            category = "plugins"
            if issubclass(plugin, ApplicationPlugin):
                category = "application_plugins"

            package = packages_by_name[canonicalize_name(entry_point.name)]
            plugins[package.pretty_name]["package"] = package
            plugins[package.pretty_name][category].append(entry_point)

        for name, info in plugins.items():
            package = info["package"]
            self.line("")
            self.line("  • <c1>{}</c1> (<c2>{}</c2>){}".format(
                name,
                package.version,
                " " + package.description if package.description else "",
            ))
            provide_line = "     "
            if info["plugins"]:
                provide_line += " <info>{}</info> plugin{}".format(
                    len(info["plugins"]),
                    "s" if len(info["plugins"]) > 1 else "")

            if info["application_plugins"]:
                if info["plugins"]:
                    provide_line += " and"

                provide_line += " <info>{}</info> application plugin{}".format(
                    len(info["application_plugins"]),
                    "s" if len(info["application_plugins"]) > 1 else "",
                )

            self.line(provide_line)

            if package.requires:
                self.line("")
                self.line("      <info>Dependencies</info>")
                for dependency in package.requires:
                    self.line("        - {} (<c2>{}</c2>)".format(
                        dependency.pretty_name, dependency.pretty_constraint))

        return 0
Пример #16
0
    def _system_project_handle(self) -> int:
        from poetry.plugins.application_plugin import ApplicationPlugin
        from poetry.plugins.plugin import Plugin
        from poetry.plugins.plugin_manager import PluginManager
        from poetry.repositories.installed_repository import InstalledRepository
        from poetry.utils.env import EnvManager
        from poetry.utils.helpers import canonicalize_name
        from poetry.utils.helpers import pluralize

        plugins: dict[str, PluginPackage] = {}

        system_env = EnvManager.get_system_env(naive=True)
        entry_points = PluginManager(
            ApplicationPlugin.group).get_plugin_entry_points(
                env=system_env) + PluginManager(
                    Plugin.group).get_plugin_entry_points(env=system_env)
        installed_repository = InstalledRepository.load(system_env,
                                                        with_dependencies=True)

        packages_by_name: dict[str, Package] = {
            pkg.name: pkg
            for pkg in installed_repository.packages
        }

        for entry_point in entry_points:
            plugin = entry_point.load()

            assert entry_point.distro is not None
            package = packages_by_name[canonicalize_name(
                entry_point.distro.name)]

            name = package.pretty_name
            info = plugins.get(name) or PluginPackage(package=package)

            if issubclass(plugin, ApplicationPlugin):
                info.application_plugins.append(entry_point)
            else:
                info.plugins.append(entry_point)

            plugins[name] = info

        for name, info in plugins.items():
            package = info.package
            description = " " + package.description if package.description else ""
            self.line("")
            self.line(
                f"  • <c1>{name}</c1> (<c2>{package.version}</c2>){description}"
            )
            provide_line = "     "

            if info.plugins:
                count = len(info.plugins)
                provide_line += f" <info>{count}</info> plugin{pluralize(count)}"

            if info.application_plugins:
                if info.plugins:
                    provide_line += " and"

                count = len(info.application_plugins)
                provide_line += (
                    f" <info>{count}</info> application plugin{pluralize(count)}"
                )

            self.line(provide_line)

            if package.requires:
                self.line("")
                self.line("      <info>Dependencies</info>")
                for dependency in package.requires:
                    self.line(f"        - {dependency.pretty_name}"
                              f" (<c2>{dependency.pretty_constraint}</c2>)")

        return 0
Пример #17
0
    def handle(self) -> int:
        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.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, packages)
                        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=[],
            locked=locked_packages,
            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 canonicalize_name(package) == 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_packages,
                                                  why_package=pkg)

                else:
                    self.display_package_tree(self.io, pkg, locked_packages)

                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.packages)

                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.packages)
                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 0
Пример #18
0
    def handle(self):
        from poetry.packages.constraints import (
            parse_constraint as parse_generic_constraint, )
        from poetry.repositories.installed_repository import InstalledRepository
        from poetry.semver import Version
        from poetry.semver import parse_constraint

        package = self.argument("package")

        if self.option("tree"):
            self.init_styles()

        if self.option("outdated"):
            self.input.set_option("latest", True)

        locked_repo = self.poetry.locker.locked_repository(
            not self.option("no-dev"))

        # 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(package, locked_repo)
                        break

            return 0

        table = self.table(style="compact")
        table.get_style().set_vertical_border_char("")
        locked_packages = locked_repo.packages

        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(pkg, locked_repo)

                return 0

            rows = [
                ["<info>name</>", " : <fg=cyan>{}</>".format(pkg.pretty_name)],
                [
                    "<info>version</>",
                    " : <comment>{}</>".format(pkg.pretty_version)
                ],
                ["<info>description</>", " : {}".format(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(" - {} <comment>{}</>".format(
                        dependency.pretty_name, dependency.pretty_constraint))

            return 0

        show_latest = self.option("latest")
        show_all = self.option("all")
        terminal = self.get_application().terminal
        width = terminal.width
        name_length = version_length = latest_length = 0
        latest_packages = {}
        installed_repo = InstalledRepository.load(self.env)
        skipped = []

        python = Version.parse(".".join(
            [str(i) for i in self.env.version_info[:3]]))

        # Computing widths
        for locked in locked_packages:
            python_constraint = locked.python_constraint
            if not python_constraint.allows(
                    python) or not self.env.is_valid_for_marker(locked.marker):
                skipped.append(locked)

                if not show_all:
                    continue

            current_length = len(locked.pretty_name)
            if not self.output.is_decorated():
                installed_status = self.get_installed_status(
                    locked, installed_repo)

                if installed_status == "not-installed":
                    current_length += 4

            name_length = max(name_length, current_length)
            version_length = max(version_length,
                                 len(locked.full_pretty_version))
            if show_latest:
                latest = self.find_latest_package(locked)
                if not latest:
                    latest = locked

                latest_packages[locked.pretty_name] = latest
                latest_length = max(latest_length,
                                    len(latest.full_pretty_version))

        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 = "green"
            name = locked.pretty_name
            install_marker = ""
            if locked in skipped:
                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.output.is_decorated():
                        # Non installed in non decorated mode
                        install_marker = " (!)"

            line = "<fg={}>{:{}}{}</>".format(
                color, name, name_length - len(install_marker), install_marker)
            if write_version:
                line += " <comment>{:{}}</comment>".format(
                    locked.full_pretty_version, version_length)
            if show_latest and write_latest:
                latest = latest_packages[locked.pretty_name]

                update_status = self.get_update_status(latest, locked)
                color = "green"
                if update_status == "semver-safe-update":
                    color = "red"
                elif update_status == "update-possible":
                    color = "yellow"

                line += " <fg={}>{:{}}</>".format(color, latest.pretty_version,
                                                  latest_length)
                if self.option("outdated") and update_status == "up-to-date":
                    continue

            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)
Пример #19
0
def repository(mocker: MockerFixture, env: MockEnv) -> InstalledRepository:
    mocker.patch(
        "poetry.utils._compat.metadata.Distribution.discover",
        return_value=INSTALLED_RESULTS,
    )
    return InstalledRepository.load(env)
Пример #20
0
    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)
Пример #21
0
 def _get_installed(self):  # type: () -> InstalledRepository
     return InstalledRepository.load(self._env)
Пример #22
0
def installed():
    return InstalledRepository()
Пример #23
0
 def _get_installed(self):  # type: () -> InstalledRepository
     return InstalledRepository.load(self._venv)
Пример #24
0
def installed():
    repository = InstalledRepository()

    repository.add_package(Package("poetry", __version__))

    return repository
Пример #25
0
    def handle(self):
        from poetry.packages.constraints.generic_constraint import GenericConstraint
        from poetry.repositories.installed_repository import InstalledRepository
        from poetry.semver import Version
        from poetry.semver import parse_constraint

        package = self.argument("package")

        if self.option("tree"):
            self.init_styles()

        if self.option("outdated"):
            self.input.set_option("latest", True)

        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(package, locked_repo)
                        break

            return 0

        table = self.table(style="compact")
        table.get_style().set_vertical_border_char("")
        locked_packages = locked_repo.packages

        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(pkg, locked_repo)

                return 0

            rows = [
                ["<info>name</>", " : <fg=cyan>{}</>".format(pkg.pretty_name)],
                ["<info>version</>", " : <comment>{}</>".format(pkg.pretty_version)],
                ["<info>description</>", " : {}".format(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(
                        " - {} <comment>{}</>".format(
                            dependency.pretty_name, dependency.pretty_constraint
                        )
                    )

            return 0

        show_latest = self.option("latest")
        show_all = self.option("all")
        terminal = self.get_application().terminal
        width = terminal.width
        name_length = version_length = latest_length = 0
        latest_packages = {}
        installed_repo = InstalledRepository.load(self.venv)
        skipped = []

        platform = sys.platform
        python = Version.parse(".".join([str(i) for i in self._venv.version_info[:3]]))

        # Computing widths
        for locked in locked_packages:
            python_constraint = parse_constraint(locked.requirements.get("python", "*"))
            platform_constraint = GenericConstraint.parse(
                locked.requirements.get("platform", "*")
            )
            if not python_constraint.allows(python) or not platform_constraint.matches(
                GenericConstraint("=", platform)
            ):
                skipped.append(locked)

                if not show_all:
                    continue

            current_length = len(locked.pretty_name)
            if not self.output.is_decorated():
                installed_status = self.get_installed_status(locked, installed_repo)

                if installed_status == "not-installed":
                    current_length += 4

            name_length = max(name_length, current_length)
            version_length = max(version_length, len(locked.full_pretty_version))
            if show_latest:
                latest = self.find_latest_package(locked)
                if not latest:
                    latest = locked

                latest_packages[locked.pretty_name] = latest
                latest_length = max(latest_length, len(latest.full_pretty_version))

        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 = "green"
            name = locked.pretty_name
            install_marker = ""
            if locked in skipped:
                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.output.is_decorated():
                        # Non installed in non decorated mode
                        install_marker = " (!)"

            line = "<fg={}>{:{}}{}</>".format(
                color, name, name_length - len(install_marker), install_marker
            )
            if write_version:
                line += " <comment>{:{}}</comment>".format(
                    locked.full_pretty_version, version_length
                )
            if show_latest and write_latest:
                latest = latest_packages[locked.pretty_name]

                update_status = self.get_update_status(latest, locked)
                color = "green"
                if update_status == "semver-safe-update":
                    color = "red"
                elif update_status == "update-possible":
                    color = "yellow"

                line += " <fg={}>{:{}}</>".format(
                    color, latest.pretty_version, latest_length
                )
                if self.option("outdated") and update_status == "up-to-date":
                    continue

            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)
Пример #26
0
    def handle(self) -> int:
        from poetry.plugins.application_plugin import ApplicationPlugin
        from poetry.plugins.plugin import Plugin
        from poetry.plugins.plugin_manager import PluginManager
        from poetry.repositories.installed_repository import InstalledRepository
        from poetry.utils.env import EnvManager
        from poetry.utils.helpers import canonicalize_name
        from poetry.utils.helpers import pluralize

        plugins: dict[str, dict[str,
                                Any]] = defaultdict(lambda: {
                                    "package": None,
                                    "plugins": [],
                                    "application_plugins": [],
                                })

        entry_points = (
            PluginManager(ApplicationPlugin.group).get_plugin_entry_points() +
            PluginManager(Plugin.group).get_plugin_entry_points())

        system_env = EnvManager.get_system_env(naive=True)
        installed_repository = InstalledRepository.load(system_env,
                                                        with_dependencies=True)

        packages_by_name = {
            pkg.name: pkg
            for pkg in installed_repository.packages
        }

        for entry_point in entry_points:
            plugin = entry_point.load()
            category = "plugins"
            if issubclass(plugin, ApplicationPlugin):
                category = "application_plugins"

            package = packages_by_name[canonicalize_name(
                entry_point.distro.name)]
            plugins[package.pretty_name]["package"] = package
            plugins[package.pretty_name][category].append(entry_point)

        for name, info in plugins.items():
            package = info["package"]
            description = " " + package.description if package.description else ""
            self.line("")
            self.line(
                f"  • <c1>{name}</c1> (<c2>{package.version}</c2>){description}"
            )
            provide_line = "     "
            if info["plugins"]:
                count = len(info["plugins"])
                provide_line += f" <info>{count}</info> plugin{pluralize(count)}"

            if info["application_plugins"]:
                if info["plugins"]:
                    provide_line += " and"

                count = len(info["application_plugins"])
                provide_line += (
                    f" <info>{count}</info> application plugin{pluralize(count)}"
                )

            self.line(provide_line)

            if package.requires:
                self.line("")
                self.line("      <info>Dependencies</info>")
                for dependency in package.requires:
                    self.line(f"        - {dependency.pretty_name}"
                              f" (<c2>{dependency.pretty_constraint}</c2>)")

        return 0
Пример #27
0
    def handle(self):
        from poetry.packages.constraints.generic_constraint import GenericConstraint
        from poetry.repositories.installed_repository import InstalledRepository
        from poetry.semver import Version
        from poetry.semver import parse_constraint

        package = self.argument('package')

        if self.option('tree'):
            self.init_styles()

        if self.option('outdated'):
            self.input.set_option('latest', True)

        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(package, locked_repo)
                        break

            return 0

        table = self.table(style='compact')
        table.get_style().set_vertical_border_char('')
        locked_packages = locked_repo.packages

        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(pkg, locked_repo)

                return 0

            rows = [
                ['<info>name</>', ' : <fg=cyan>{}</>'.format(pkg.pretty_name)],
                ['<info>version</>', ' : <comment>{}</>'.format(pkg.pretty_version)],
                ['<info>description</>', ' : {}'.format(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(
                        ' - {} <comment>{}</>'.format(
                            dependency.pretty_name,
                            dependency.pretty_constraint
                        )
                    )

            return 0

        show_latest = self.option('latest')
        show_all = self.option('all')
        terminal = self.get_application().terminal
        width = terminal.width
        name_length = version_length = latest_length = 0
        latest_packages = {}
        installed_repo = InstalledRepository.load(self.venv)
        skipped = []

        platform = sys.platform
        python = Version.parse('.'.join([str(i) for i in self._venv.version_info[:3]]))

        # Computing widths
        for locked in locked_packages:
            python_constraint = parse_constraint(locked.requirements.get('python', '*'))
            platform_constraint = GenericConstraint.parse(locked.requirements.get('platform', '*'))
            if (
                not python_constraint.allows(python)
                or not platform_constraint.matches(GenericConstraint('=', platform))
            ):
                skipped.append(locked)

                if not show_all:
                    continue

            current_length = len(locked.pretty_name)
            if not self.output.is_decorated():
                installed_status = self.get_installed_status(locked, installed_repo)

                if installed_status == 'not-installed':
                    current_length += 4

            name_length = max(name_length, current_length)
            version_length = max(version_length, len(locked.full_pretty_version))
            if show_latest:
                latest = self.find_latest_package(locked)
                if not latest:
                    latest = locked

                latest_packages[locked.pretty_name] = latest
                latest_length = max(latest_length, len(latest.full_pretty_version))

        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 = 'green'
            name = locked.pretty_name
            install_marker = ''
            if locked in skipped:
                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.output.is_decorated():
                        # Non installed in non decorated mode
                        install_marker = ' (!)'

            line = '<fg={}>{:{}}{}</>'.format(color, name, name_length - len(install_marker), install_marker)
            if write_version:
                line += ' {:{}}'.format(
                    locked.full_pretty_version, version_length
                )
            if show_latest and write_latest:
                latest = latest_packages[locked.pretty_name]

                update_status = self.get_update_status(latest, locked)
                color = 'green'
                if update_status == 'semver-safe-update':
                    color = 'red'
                elif update_status == 'update-possible':
                    color = 'yellow'

                line += ' <fg={}>{:{}}</>'.format(
                    color, latest.pretty_version, latest_length
                )
                if self.option('outdated') and update_status == 'up-to-date':
                    continue

            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)