Source code for ubelt.util_mixins

# -*- coding: utf-8 -*-
"""
This module defines the `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`.
"""
from __future__ import absolute_import, division, print_function, unicode_literals
import warnings


[docs]class NiceRepr(object): """ Defines `__str__` and `__repr__` in terms of `__nice__` function Classes that inherit from `NiceRepr` must define `__nice__` Example: >>> import ubelt as ub >>> class Foo(ub.NiceRepr): ... def __nice__(self): ... return 'info' >>> foo = Foo() >>> assert str(foo) == '<Foo(info)>' >>> assert repr(foo).startswith('<Foo(info) at ') Example: >>> import ubelt as ub >>> class Bar(ub.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: >>> import ubelt as ub >>> class Baz(ub.NiceRepr): ... def __len__(self): ... return 5 >>> baz = Baz() >>> assert str(baz) == '<Baz(5)>' """ def __nice__(self): if hasattr(self, '__len__'): # It is a common pattern for objects to use __len__ in __nice__ # As a convenience we define a default __nice__ for these objects return str(len(self)) else: # In all other cases force the subclass to overload __nice__ raise NotImplementedError( 'Define the __nice__ method for %r' % (self.__class__,)) def __repr__(self): try: devnice = self.__nice__() classname = self.__class__.__name__ return '<%s(%s) at %s>' % (classname, devnice, hex(id(self))) except NotImplementedError as ex: warnings.warn(str(ex), category=RuntimeWarning) return object.__repr__(self) def __str__(self): try: classname = self.__class__.__name__ devnice = self.__nice__() return '<%s(%s)>' % (classname, devnice) except NotImplementedError as ex: warnings.warn(str(ex), category=RuntimeWarning) return object.__repr__(self)