| |
| """This module defines the :class:`NiceRepr` mixin class, which defines a |
| ``__repr__`` and ``__str__`` method that only depend on a custom ``__nice__`` |
| method, which you must define. This means you only have to overload one |
| function instead of two. Furthermore, if the object defines a ``__len__`` |
| method, then the ``__nice__`` method defaults to something sensible, otherwise |
| it is treated as abstract and raises ``NotImplementedError``. |
| |
| To use simply have your object inherit from :class:`NiceRepr` |
| (multi-inheritance should be ok). |
| |
| This code was copied from the ubelt library: https://github.com/Erotemic/ubelt |
| |
| Example: |
| >>> # Objects that define __nice__ have a default __str__ and __repr__ |
| >>> class Student(NiceRepr): |
| ... def __init__(self, name): |
| ... self.name = name |
| ... def __nice__(self): |
| ... return self.name |
| >>> s1 = Student('Alice') |
| >>> s2 = Student('Bob') |
| >>> print(f's1 = {s1}') |
| >>> print(f's2 = {s2}') |
| s1 = <Student(Alice)> |
| s2 = <Student(Bob)> |
| |
| Example: |
| >>> # Objects that define __len__ have a default __nice__ |
| >>> class Group(NiceRepr): |
| ... def __init__(self, data): |
| ... self.data = data |
| ... def __len__(self): |
| ... return len(self.data) |
| >>> g = Group([1, 2, 3]) |
| >>> print(f'g = {g}') |
| g = <Group(3)> |
| """ |
| import warnings |
|
|
|
|
| class NiceRepr: |
| """Inherit from this class and define ``__nice__`` to "nicely" print your |
| objects. |
| |
| Defines ``__str__`` and ``__repr__`` in terms of ``__nice__`` function |
| Classes that inherit from :class:`NiceRepr` should redefine ``__nice__``. |
| If the inheriting class has a ``__len__``, method then the default |
| ``__nice__`` method will return its length. |
| |
| Example: |
| >>> class Foo(NiceRepr): |
| ... def __nice__(self): |
| ... return 'info' |
| >>> foo = Foo() |
| >>> assert str(foo) == '<Foo(info)>' |
| >>> assert repr(foo).startswith('<Foo(info) at ') |
| |
| Example: |
| >>> class Bar(NiceRepr): |
| ... pass |
| >>> bar = Bar() |
| >>> import pytest |
| >>> with pytest.warns(None) as record: |
| >>> assert 'object at' in str(bar) |
| >>> assert 'object at' in repr(bar) |
| |
| Example: |
| >>> class Baz(NiceRepr): |
| ... def __len__(self): |
| ... return 5 |
| >>> baz = Baz() |
| >>> assert str(baz) == '<Baz(5)>' |
| """ |
|
|
| def __nice__(self): |
| """str: a "nice" summary string describing this module""" |
| if hasattr(self, '__len__'): |
| |
| |
| return str(len(self)) |
| else: |
| |
| raise NotImplementedError( |
| f'Define the __nice__ method for {self.__class__!r}') |
|
|
| def __repr__(self): |
| """str: the string of the module""" |
| try: |
| nice = self.__nice__() |
| classname = self.__class__.__name__ |
| return f'<{classname}({nice}) at {hex(id(self))}>' |
| except NotImplementedError as ex: |
| warnings.warn(str(ex), category=RuntimeWarning) |
| return object.__repr__(self) |
|
|
| def __str__(self): |
| """str: the string of the module""" |
| try: |
| classname = self.__class__.__name__ |
| nice = self.__nice__() |
| return f'<{classname}({nice})>' |
| except NotImplementedError as ex: |
| warnings.warn(str(ex), category=RuntimeWarning) |
| return object.__repr__(self) |
|
|