• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 18517631058

15 Oct 2025 04:18AM UTC coverage: 69.207% (-11.1%) from 80.267%
18517631058

Pull #22745

github

web-flow
Merge 642a76ca1 into 99919310e
Pull Request #22745: [windows] Add windows support in the stdio crate.

53815 of 77759 relevant lines covered (69.21%)

2.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

44.26
/src/python/pants/help/help_tools.py
1
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3
from __future__ import annotations
7✔
4

5
from collections.abc import Generator, Iterable
7✔
6
from dataclasses import dataclass
7✔
7
from functools import partial
7✔
8
from itertools import chain
7✔
9
from textwrap import wrap
7✔
10
from typing import cast
7✔
11

12
from pants.help.help_info_extracter import AllHelpInfo, OptionScopeHelpInfo
7✔
13
from pants.help.maybe_color import MaybeColor
7✔
14
from pants.util.docutil import terminal_width
7✔
15

16

17
@dataclass(frozen=True)
7✔
18
class ToolHelpInfo:
7✔
19
    name: str
7✔
20
    description: str
7✔
21
    version: str
7✔
22
    url_template: str | None
7✔
23

24
    @classmethod
7✔
25
    def from_option_scope_help_info(cls, oshi: OptionScopeHelpInfo) -> ToolHelpInfo | None:
7✔
26
        version, url_template = cls._get_tool_info(oshi)
×
27
        if not version:
×
28
            return None
×
29
        return cls(
×
30
            name=oshi.scope,
31
            description=oshi.description,
32
            version=version,
33
            url_template=url_template,
34
        )
35

36
    @classmethod
7✔
37
    def iter(cls, all_help_info: AllHelpInfo) -> Generator[ToolHelpInfo, None, None]:
7✔
38
        for oshi in all_help_info.non_deprecated_option_scope_help_infos():
×
39
            tool_info = cls.from_option_scope_help_info(oshi)
×
40
            if tool_info:
×
41
                yield tool_info
×
42

43
    @staticmethod
7✔
44
    def print_all(tool_help_infos: Iterable[ToolHelpInfo], color: MaybeColor) -> None:
7✔
45
        this = tuple(tool_help_infos)
×
46
        longest_name = max(len(tool.name) for tool in this)
×
47
        width = terminal_width()
×
48

49
        for tool in this:
×
50
            tool.print(color, description_padding=longest_name + 2, width=width)
×
51

52
    def print(self, color: MaybeColor, description_padding: int, width: int) -> None:
7✔
53
        _wrap = partial(wrap, width=width)
×
54
        _max_padding = partial(
×
55
            min, int(width / 4)
56
        )  # Do not use more than 25% of the width on padding.
57

58
        def _indent(indent: int) -> str:
×
59
            return " " * cast(int, _max_padding(indent))
×
60

61
        lines = _wrap(
×
62
            f"{self.name.ljust(description_padding)}{self.description}",
63
            subsequent_indent=_indent(description_padding),
64
        )
65
        lines[0] = lines[0].replace(self.name, color.maybe_cyan(self.name), 1)
×
66
        version = _wrap(
×
67
            f"Version: {self.version}",
68
            initial_indent=_indent(description_padding),
69
            subsequent_indent=_indent(description_padding),
70
        )
71
        if not self.url_template:
×
72
            url_template = []
×
73
        else:
74
            url_template = _wrap(
×
75
                f"URL template: {self.url_template}",
76
                initial_indent=_indent(description_padding),
77
                subsequent_indent=_indent(description_padding),
78
            )
79
        print("\n".join(lines))
×
80
        print(color.maybe_magenta("\n".join([*version, *url_template, ""])))
×
81

82
    @classmethod
7✔
83
    def _get_tool_info(cls, oshi: OptionScopeHelpInfo) -> tuple[str | None, str | None]:
7✔
84
        return (
×
85
            cls._get_option_value(oshi, "version"),
86
            cls._get_option_value(oshi, "url_template"),
87
        )
88

89
    @staticmethod
7✔
90
    def _get_option_value(oshi: OptionScopeHelpInfo, config_key: str) -> str | None:
7✔
91
        for ohi in chain(oshi.basic, oshi.advanced):
×
92
            if ohi.config_key == config_key and ohi.typ is str:
×
93
                rank = ohi.value_history and ohi.value_history.final_value
×
94
                if rank:
×
95
                    info = f" ({rank.details})" if rank.details else ""
×
96
                    return f"{rank.value}{info}"
×
97
                return cast(str, ohi.default)
×
98
        return None
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc