• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2023 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4""" A collection of helpers that rely on non-crossbench code."""
5
6from __future__ import annotations
7
8import enum
9import os
10import sys
11import textwrap
12from typing import List, NamedTuple, Optional, Tuple, Type, TypeVar, cast
13
14import tabulate
15
16from crossbench import path as pth
17
18if sys.version_info >= (3, 11):
19  from enum import StrEnum  # pylint: disable=unused-import
20else:
21
22  class StrEnum(str, enum.Enum):
23
24    def __str__(self) -> str:
25      return str(self.value)
26
27
28if sys.version_info >= (3, 9):
29
30  def is_relative_to(path_a: pth.AnyPath, path_b: pth.AnyPath) -> bool:
31    return path_a.is_relative_to(path_b)
32
33  def readlink(path: pth.LocalPath) -> pth.LocalPath:
34    return path.readlink()
35else:
36
37  def is_relative_to(path_a: pth.AnyPath, path_b: pth.AnyPath) -> bool:
38    try:
39      path_a.relative_to(path_b)
40      return True
41    except ValueError:
42      return False
43
44  def readlink(path: pth.LocalPath) -> pth.LocalPath:
45    return pth.LocalPath(os.readlink(path))
46
47
48class StrHelpDataMixin(NamedTuple):
49  value: str
50  help: str
51
52
53StrEnumWithHelpT = TypeVar("StrEnumWithHelpT", bound="StrEnumWithHelp")
54
55class StrEnumWithHelp(StrHelpDataMixin, enum.Enum):
56
57  @classmethod
58  def _missing_(cls: Type[StrEnumWithHelpT],
59                value) -> Optional[StrEnumWithHelpT]:
60    value = str(value).lower()
61    for member in cls:
62      if member.value == value:
63        return member
64    return None
65
66  @classmethod
67  def help_text_items(cls) -> List[Tuple[str, str]]:
68    return [
69        (repr(instance.value), instance.help) for instance in cls  # pytype: disable=missing-parameter
70    ]
71
72  @classmethod
73  def help_text(cls, indent: int = 0) -> str:
74    text: str = tabulate.tabulate(cls.help_text_items(), tablefmt="plain")
75    if indent:
76      return textwrap.indent(text, " " * indent)
77    return text
78
79  def __str__(self) -> str:
80    return cast(str, self.value)
81