pytermgui.fancy_repr
The __fancy_repl__
protocol.
1"""The `__fancy_repl__` protocol.""" 2 3from __future__ import annotations 4 5from typing import Dict, Generator, Protocol, Union 6 7from .highlighters import highlight_python 8 9FancyYield = Union[str, Dict[str, Union[str, bool]]] 10 11__all__ = [ 12 "SupportsFancyRepr", 13 "supports_fancy_repr", 14 "build_fancy_repr", 15] 16 17 18class SupportsFancyRepr(Protocol): # pylint: disable=too-few-public-methods 19 """An object that supports the `__fancy_repr__` dunder.""" 20 21 def __fancy_repr__(self) -> Generator[FancyYield, None, None]: 22 """Yields some fancy text. 23 24 Each value yielded can be one of two types. If a dictionary is yielded, 25 it will be assumed to have `text` and `highlight` fields. `text` will be 26 the string included in the repr, and `highlight` will be a boolean describing 27 whether the part should be highlighted. At the moment highlighting is done by 28 `highlight_python`, but this might be configurable once more highlighters are 29 available. 30 31 If a `str` is yielded, it is assumed to be a shorthand for: 32 33 {"text": <your_text>, "highlight": True} 34 """ 35 36 37def supports_fancy_repr(obj: object) -> bool: 38 """Determines whether the given object supports the fancy repl protocol.""" 39 40 return hasattr(obj, "__fancy_repr__") and not isinstance(obj, type) 41 42 43def build_fancy_repr(obj: SupportsFancyRepr) -> str: 44 """Interprets objects with the `__fancy_repr__` protocol.""" 45 46 output = "" 47 for item in obj.__fancy_repr__(): 48 if isinstance(item, str): 49 output += highlight_python(item) 50 continue 51 52 text = item["text"] 53 assert isinstance(text, str) 54 55 highlight = item["highlight"] 56 57 if highlight: 58 text = highlight_python(text) 59 60 output += text 61 62 return output
class
SupportsFancyRepr(typing.Protocol):
19class SupportsFancyRepr(Protocol): # pylint: disable=too-few-public-methods 20 """An object that supports the `__fancy_repr__` dunder.""" 21 22 def __fancy_repr__(self) -> Generator[FancyYield, None, None]: 23 """Yields some fancy text. 24 25 Each value yielded can be one of two types. If a dictionary is yielded, 26 it will be assumed to have `text` and `highlight` fields. `text` will be 27 the string included in the repr, and `highlight` will be a boolean describing 28 whether the part should be highlighted. At the moment highlighting is done by 29 `highlight_python`, but this might be configurable once more highlighters are 30 available. 31 32 If a `str` is yielded, it is assumed to be a shorthand for: 33 34 {"text": <your_text>, "highlight": True} 35 """
An object that supports the __fancy_repr__
dunder.
SupportsFancyRepr(*args, **kwargs)
1430def _no_init_or_replace_init(self, *args, **kwargs): 1431 cls = type(self) 1432 1433 if cls._is_protocol: 1434 raise TypeError('Protocols cannot be instantiated') 1435 1436 # Already using a custom `__init__`. No need to calculate correct 1437 # `__init__` to call. This can lead to RecursionError. See bpo-45121. 1438 if cls.__init__ is not _no_init_or_replace_init: 1439 return 1440 1441 # Initially, `__init__` of a protocol subclass is set to `_no_init_or_replace_init`. 1442 # The first instantiation of the subclass will call `_no_init_or_replace_init` which 1443 # searches for a proper new `__init__` in the MRO. The new `__init__` 1444 # replaces the subclass' old `__init__` (ie `_no_init_or_replace_init`). Subsequent 1445 # instantiation of the protocol subclass will thus use the new 1446 # `__init__` and no longer call `_no_init_or_replace_init`. 1447 for base in cls.__mro__: 1448 init = base.__dict__.get('__init__', _no_init_or_replace_init) 1449 if init is not _no_init_or_replace_init: 1450 cls.__init__ = init 1451 break 1452 else: 1453 # should not happen 1454 cls.__init__ = object.__init__ 1455 1456 cls.__init__(self, *args, **kwargs)
def
supports_fancy_repr(obj: object) -> bool:
38def supports_fancy_repr(obj: object) -> bool: 39 """Determines whether the given object supports the fancy repl protocol.""" 40 41 return hasattr(obj, "__fancy_repr__") and not isinstance(obj, type)
Determines whether the given object supports the fancy repl protocol.
44def build_fancy_repr(obj: SupportsFancyRepr) -> str: 45 """Interprets objects with the `__fancy_repr__` protocol.""" 46 47 output = "" 48 for item in obj.__fancy_repr__(): 49 if isinstance(item, str): 50 output += highlight_python(item) 51 continue 52 53 text = item["text"] 54 assert isinstance(text, str) 55 56 highlight = item["highlight"] 57 58 if highlight: 59 text = highlight_python(text) 60 61 output += text 62 63 return output
Interprets objects with the __fancy_repr__
protocol.