Coverage for /run/media/veganeco/water/status600.com/pypi/reptilian_climates/modules_series_2/ships/fields/gardens_pip/rich/repr.py: 39%

1 import inspect

2 from functools import partial

3 from typing import (

4 Any,

5 Callable,

6 Iterable,

7 List,

8 Optional,

9 Tuple,

10 Type,

11 TypeVar,

12 Union,

13 overload,

14)

15

16 T = TypeVar("T")

17

18

19 Result = Iterable[Union[Any, Tuple[Any], Tuple[str, Any], Tuple[str, Any, Any]]]

20 RichReprResult = Result

21

22

23 class ReprError(Exception):

24 """An error occurred when attempting to build a repr."""

25

26

27@overload

28 def auto(cls: Optional[Type[T]]) -> Type[T]:

29 ...

30

31

32@overload

33 def auto(*, angular: bool = False) -> Callable[[Type[T]], Type[T]]:

34 ...

35

36

37 def auto(

38 cls: Optional[Type[T]] = None, *, angular: Optional[bool] = None

39) -> Union[Type[T], Callable[[Type[T]], Type[T]]]:

40 """Class decorator to create __repr__ from __rich_repr__"""

41

42 def do_replace(cls: Type[T], angular: Optional[bool] = None) -> Type[T]:

43 def auto_repr(self: T) -> str:

44 """Create repr string from __rich_repr__"""

45 repr_str: List[str] = []

46 append = repr_str.append

47

48 angular: bool = getattr(self.__rich_repr__, "angular", False) # type: ignore[attr-defined]

49 for arg in self.__rich_repr__(): # type: ignore[attr-defined]

50 if isinstance(arg, tuple):

51 if len(arg) == 1:

52 append(repr(arg[0]))

53 else:

54 key, value, *default = arg

55 if key is None:

56 append(repr(value))

57 else:

58 if default and default[0] == value:

59 continue

60 append(f"{key}={value!r}")

61 else:

62 append(repr(arg))

63 if angular:

64 return f"<{self.__class__.__name__} {' '.join(repr_str)}>"

65 else:

66 return f"{self.__class__.__name__}({', '.join(repr_str)})"

67

68 def auto_rich_repr(self: Type[T]) -> Result:

69 """Auto generate __rich_rep__ from signature of __init__"""

70 try:

71 signature = inspect.signature(self.__init__)

72 for name, param in signature.parameters.items():

73 if param.kind == param.POSITIONAL_ONLY:

74 yield getattr(self, name)

75 elif param.kind in (

76 param.POSITIONAL_OR_KEYWORD,

77 param.KEYWORD_ONLY,

78 ):

79 if param.default is param.empty:

80 yield getattr(self, param.name)

81 else:

82 yield param.name, getattr(self, param.name), param.default

83 except Exception as error:

84 raise ReprError(

85 f"Failed to auto generate __rich_repr__; {error}"

86 ) from None

87

88 if not hasattr(cls, "__rich_repr__"):

89 auto_rich_repr.__doc__ = "Build a rich repr"

90 cls.__rich_repr__ = auto_rich_repr # type: ignore[attr-defined]

91

92 auto_repr.__doc__ = "Return repr(self)"

93 cls.__repr__ = auto_repr # type: ignore[assignment]

94 if angular is not None:

95 cls.__rich_repr__.angular = angular # type: ignore[attr-defined]

96 return cls

97

98 if cls is None:

99 return partial(do_replace, angular=angular)

100 else:

101 return do_replace(cls, angular=angular)

102

103

104@overload

105 def rich_repr(cls: Optional[Type[T]]) -> Type[T]:

106 ...

107

108

109@overload

110 def rich_repr(*, angular: bool = False) -> Callable[[Type[T]], Type[T]]:

111 ...

112

113

114 def rich_repr(

115 cls: Optional[Type[T]] = None, *, angular: bool = False

116) -> Union[Type[T], Callable[[Type[T]], Type[T]]]:

117 if cls is None:

118 return auto(angular=angular)

119 else:

120 return auto(cls)

121

122

123 if __name__ == "__main__":

124

125 @auto

126 class Foo:

127 def __rich_repr__(self) -> Result:

128 yield "foo"

129 yield "bar", {"shopping": ["eggs", "ham", "pineapple"]}

130 yield "buy", "hand sanitizer"

131

132 foo = Foo()

133 from rich.console import Console

134

135 console = Console()

136

137 console.rule("Standard repr")

138 console.print(foo)

139

140 console.print(foo, width=60)

141 console.print(foo, width=30)

142

143 console.rule("Angular repr")

144 Foo.__rich_repr__.angular = True # type: ignore[attr-defined]

145

146 console.print(foo)

147

148 console.print(foo, width=60)

149 console.print(foo, width=30)