Coverage for pydantic/_internal/_repr.py: 100.00%
66 statements
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-03 19:29 +0000
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-03 19:29 +0000
1"""Tools to provide pretty/human-readable display of objects."""
3from __future__ import annotations as _annotations 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
5import types 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
6import typing 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
7from typing import Any 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
9import typing_extensions 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
11from . import _typing_extra 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
13if typing.TYPE_CHECKING: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
14 ReprArgs: typing_extensions.TypeAlias = 'typing.Iterable[tuple[str | None, Any]]'
15 RichReprResult: typing_extensions.TypeAlias = (
16 'typing.Iterable[Any | tuple[Any] | tuple[str, Any] | tuple[str, Any, Any]]'
17 )
20class PlainRepr(str): 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
21 """String class where repr doesn't include quotes. Useful with Representation when you want to return a string
22 representation of something that is valid (or pseudo-valid) python.
23 """
25 def __repr__(self) -> str: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
26 return str(self) 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
29class Representation: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
30 # Mixin to provide `__str__`, `__repr__`, and `__pretty__` and `__rich_repr__` methods.
31 # `__pretty__` is used by [devtools](https://python-devtools.helpmanual.io/).
32 # `__rich_repr__` is used by [rich](https://rich.readthedocs.io/en/stable/pretty.html).
33 # (this is not a docstring to avoid adding a docstring to classes which inherit from Representation)
35 # we don't want to use a type annotation here as it can break get_type_hints
36 __slots__ = tuple() # type: typing.Collection[str] 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
38 def __repr_args__(self) -> ReprArgs: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
39 """Returns the attributes to show in __str__, __repr__, and __pretty__ this is generally overridden.
41 Can either return:
42 * name - value pairs, e.g.: `[('foo_name', 'foo'), ('bar_name', ['b', 'a', 'r'])]`
43 * or, just values, e.g.: `[(None, 'foo'), (None, ['b', 'a', 'r'])]`
44 """
45 attrs_names = self.__slots__ 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
46 if not attrs_names and hasattr(self, '__dict__'): 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
47 attrs_names = self.__dict__.keys() 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
48 attrs = ((s, getattr(self, s)) for s in attrs_names) 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
49 return [(a, v) for a, v in attrs if v is not None] 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
51 def __repr_name__(self) -> str: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
52 """Name of the instance's class, used in __repr__."""
53 return self.__class__.__name__ 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
55 def __repr_str__(self, join_str: str) -> str: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
56 return join_str.join(repr(v) if a is None else f'{a}={v!r}' for a, v in self.__repr_args__()) 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
58 def __pretty__(self, fmt: typing.Callable[[Any], Any], **kwargs: Any) -> typing.Generator[Any, None, None]: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
59 """Used by devtools (https://python-devtools.helpmanual.io/) to pretty print objects."""
60 yield self.__repr_name__() + '(' 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
61 yield 1 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
62 for name, value in self.__repr_args__(): 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
63 if name is not None: 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
64 yield name + '=' 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
65 yield fmt(value) 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
66 yield ',' 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
67 yield 0 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
68 yield -1 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
69 yield ')' 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
71 def __rich_repr__(self) -> RichReprResult: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
72 """Used by Rich (https://rich.readthedocs.io/en/stable/pretty.html) to pretty print objects."""
73 for name, field_repr in self.__repr_args__(): 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
74 if name is None: 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
75 yield field_repr 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
76 else:
77 yield name, field_repr 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
79 def __str__(self) -> str: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
80 return self.__repr_str__(' ') 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
82 def __repr__(self) -> str: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
83 return f'{self.__repr_name__()}({self.__repr_str__(", ")})' 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
86def display_as_type(obj: Any) -> str: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
87 """Pretty representation of a type, should be as close as possible to the original type definition string.
89 Takes some logic from `typing._type_repr`.
90 """
91 if isinstance(obj, types.FunctionType): 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
92 return obj.__name__ 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
93 elif obj is ...: 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
94 return '...' 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
95 elif isinstance(obj, Representation): 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
96 return repr(obj) 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
97 elif isinstance(obj, typing_extensions.TypeAliasType): 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
98 return str(obj) 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
100 if not isinstance(obj, (_typing_extra.typing_base, _typing_extra.WithArgsTypes, type)): 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
101 obj = obj.__class__ 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
103 if _typing_extra.origin_is_union(typing_extensions.get_origin(obj)): 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
104 args = ', '.join(map(display_as_type, typing_extensions.get_args(obj))) 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
105 return f'Union[{args}]' 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl
106 elif isinstance(obj, _typing_extra.WithArgsTypes): 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
107 if typing_extensions.get_origin(obj) == typing_extensions.Literal: 1zAmnopabcdBqCDrstuefghEFvwxyijkl
108 args = ', '.join(map(repr, typing_extensions.get_args(obj))) 1mnopabcdqrstuefghvwxyijkl
109 else:
110 args = ', '.join(map(display_as_type, typing_extensions.get_args(obj))) 1zAmnopabcdBqCDrstuefghEFvwxyijkl
111 try: 1zAmnopabcdBqCDrstuefghEFvwxyijkl
112 return f'{obj.__qualname__}[{args}]' 1zAmnopabcdBqCDrstuefghEFvwxyijkl
113 except AttributeError: 1abcdefghijkl
114 return str(obj) # handles TypeAliasType in 3.12 1abcdefghijkl
115 elif isinstance(obj, type): 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
116 return obj.__qualname__ 1GHzAmnopabcdBqIJCDrstuefghMNOPQRSTUVKLEFvwxyijkl
117 else:
118 return repr(obj).replace('typing.', '').replace('typing_extensions.', '') 1GHzAmnopabcdBqIJCDrstuefghKLEFvwxyijkl