Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python 

2# cardinal_pythonlib/reprfunc.py 

3 

4""" 

5=============================================================================== 

6 

7 Original code copyright (C) 2009-2021 Rudolf Cardinal (rudolf@pobox.com). 

8 

9 This file is part of cardinal_pythonlib. 

10 

11 Licensed under the Apache License, Version 2.0 (the "License"); 

12 you may not use this file except in compliance with the License. 

13 You may obtain a copy of the License at 

14 

15 https://www.apache.org/licenses/LICENSE-2.0 

16 

17 Unless required by applicable law or agreed to in writing, software 

18 distributed under the License is distributed on an "AS IS" BASIS, 

19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

20 See the License for the specific language governing permissions and 

21 limitations under the License. 

22 

23=============================================================================== 

24 

25**Functions to assist making repr() methods for Python objects.** 

26 

27""" 

28 

29import pprint 

30from typing import Any, Iterable, List, Tuple 

31 

32COMMA_SPACE = ", " 

33 

34 

35# ============================================================================= 

36# __repr__ aids 

37# ============================================================================= 

38# The repr() function often attempts to return something suitable for eval(); 

39# failing that, it usually shows an address. 

40# https://docs.python.org/3/library/functions.html#repr 

41 

42def repr_result(obj: Any, elements: List[str], 

43 with_addr: bool = False, joiner: str = COMMA_SPACE) -> str: 

44 """ 

45 Internal function to make a :func:`repr`-style representation of an object. 

46 

47 Args: 

48 obj: object to display 

49 elements: list of object ``attribute=value`` strings 

50 with_addr: include the memory address of ``obj`` 

51 joiner: string with which to join the elements 

52 

53 Returns: 

54 string: :func:`repr`-style representation 

55 

56 """ 

57 if with_addr: 

58 return "<{qualname}({elements}) at {addr}>".format( 

59 qualname=obj.__class__.__qualname__, 

60 elements=joiner.join(elements), 

61 addr=hex(id(obj))) 

62 else: 

63 return "{qualname}({elements})".format( 

64 qualname=obj.__class__.__qualname__, 

65 elements=joiner.join(elements)) 

66 

67 

68def auto_repr(obj: Any, with_addr: bool = False, 

69 sort_attrs: bool = True, joiner: str = COMMA_SPACE) -> str: 

70 """ 

71 Convenience function for :func:`__repr__`. 

72 Works its way through the object's ``__dict__`` and reports accordingly. 

73 

74 Args: 

75 obj: object to display 

76 with_addr: include the memory address of ``obj`` 

77 sort_attrs: sort the attributes into alphabetical order? 

78 joiner: string with which to join the elements 

79 

80 Returns: 

81 string: :func:`repr`-style representation 

82 """ 

83 if sort_attrs: 

84 keys = sorted(obj.__dict__.keys()) 

85 else: 

86 keys = obj.__dict__.keys() 

87 elements = [f"{k}={getattr(obj, k)!r}" for k in keys] 

88 return repr_result(obj, elements, with_addr=with_addr, joiner=joiner) 

89 

90 

91def simple_repr(obj: Any, attrnames: List[str], 

92 with_addr: bool = False, joiner: str = COMMA_SPACE) -> str: 

93 """ 

94 Convenience function for :func:`__repr__`. 

95 Works its way through a list of attribute names, and creates a ``repr()`` 

96 representation assuming that parameters to the constructor have the same 

97 names. 

98 

99 Args: 

100 obj: object to display 

101 attrnames: names of attributes to include 

102 with_addr: include the memory address of ``obj`` 

103 joiner: string with which to join the elements 

104 

105 Returns: 

106 string: :func:`repr`-style representation 

107 

108 """ 

109 elements = [f"{name}={getattr(obj, name)!r}" for name in attrnames] 

110 return repr_result(obj, elements, with_addr=with_addr, joiner=joiner) 

111 

112 

113def mapped_repr(obj: Any, attributes: List[Tuple[str, str]], 

114 with_addr: bool = False, joiner: str = COMMA_SPACE) -> str: 

115 """ 

116 Convenience function for :func:`__repr__`. 

117 Takes attribute names and corresponding initialization parameter names 

118 (parameters to :func:`__init__`). 

119 

120 Args: 

121 obj: object to display 

122 attributes: list of tuples, each ``(attr_name, init_param_name)``. 

123 with_addr: include the memory address of ``obj`` 

124 joiner: string with which to join the elements 

125 

126 Returns: 

127 string: :func:`repr`-style representation 

128 

129 """ 

130 elements = [f"{init_param_name}={getattr(obj, attr_name)!r}" 

131 for attr_name, init_param_name in attributes] 

132 return repr_result(obj, elements, with_addr=with_addr, joiner=joiner) 

133 

134 

135def mapped_repr_stripping_underscores( 

136 obj: Any, attrnames: List[str], 

137 with_addr: bool = False, joiner: str = COMMA_SPACE) -> str: 

138 """ 

139 Convenience function for :func:`__repr__`. 

140 Here, you pass a list of internal attributes, and it assumes that the 

141 :func:`__init__` parameter names have the leading underscore dropped. 

142 

143 Args: 

144 obj: object to display 

145 attrnames: list of attribute names 

146 with_addr: include the memory address of ``obj`` 

147 joiner: string with which to join the elements 

148 

149 Returns: 

150 string: :func:`repr`-style representation 

151 

152 """ 

153 attributes = [] 

154 for attr_name in attrnames: 

155 if attr_name.startswith('_'): 

156 init_param_name = attr_name[1:] 

157 else: 

158 init_param_name = attr_name 

159 attributes.append((attr_name, init_param_name)) 

160 return mapped_repr(obj, attributes, with_addr=with_addr, joiner=joiner) 

161 

162 

163def ordered_repr(obj: object, attrlist: Iterable[str], 

164 joiner: str = COMMA_SPACE) -> str: 

165 """ 

166 Shortcut to make :func:`repr` functions ordered. 

167 Define your :func:`__repr__` like this: 

168 

169 .. code-block:: python 

170 

171 def __repr__(self): 

172 return ordered_repr(self, ["field1", "field2", "field3"]) 

173 

174 Args: 

175 obj: object to display 

176 attrlist: iterable of attribute names 

177 joiner: string with which to join the elements 

178 

179 Returns: 

180 string: :func:`repr`-style representation 

181 """ 

182 return "<{classname}({kvp})>".format( 

183 classname=type(obj).__name__, 

184 kvp=joiner.join(f"{a}={getattr(obj, a)!r}" for a in attrlist) 

185 ) 

186 

187 

188def auto_str(obj: Any, indent: int = 4, width: int = 80, depth: int = None, 

189 compact: bool = False) -> str: 

190 """ 

191 Make a pretty :func:`str()` representation using :func:`pprint.pformat` 

192 and the object's ``__dict__`` attribute. 

193 

194 Args: 

195 obj: object to display 

196 indent: see 

197 https://docs.python.org/3/library/pprint.html#pprint.PrettyPrinter 

198 width: as above 

199 depth: as above 

200 compact: as above 

201 

202 Returns: 

203 string: :func:`str`-style representation 

204 

205 """ 

206 return pprint.pformat(obj.__dict__, indent=indent, width=width, 

207 depth=depth, compact=compact)