Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/cardinal_pythonlib/reprfunc.py : 34%

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
4"""
5===============================================================================
7 Original code copyright (C) 2009-2021 Rudolf Cardinal (rudolf@pobox.com).
9 This file is part of cardinal_pythonlib.
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
15 https://www.apache.org/licenses/LICENSE-2.0
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.
23===============================================================================
25**Functions to assist making repr() methods for Python objects.**
27"""
29import pprint
30from typing import Any, Iterable, List, Tuple
32COMMA_SPACE = ", "
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
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.
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
53 Returns:
54 string: :func:`repr`-style representation
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))
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.
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
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)
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.
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
105 Returns:
106 string: :func:`repr`-style representation
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)
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__`).
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
126 Returns:
127 string: :func:`repr`-style representation
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)
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.
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
149 Returns:
150 string: :func:`repr`-style representation
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)
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:
169 .. code-block:: python
171 def __repr__(self):
172 return ordered_repr(self, ["field1", "field2", "field3"])
174 Args:
175 obj: object to display
176 attrlist: iterable of attribute names
177 joiner: string with which to join the elements
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 )
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.
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
202 Returns:
203 string: :func:`str`-style representation
205 """
206 return pprint.pformat(obj.__dict__, indent=indent, width=width,
207 depth=depth, compact=compact)