Add _repr_pretty_ for IPython

This commit is contained in:
Lucidiot 2019-09-30 07:17:06 +02:00
parent cdf39c3464
commit e5dcb746ad
Signed by: lucidiot
GPG Key ID: 3358C1CA6906FB8D
4 changed files with 88 additions and 33 deletions

View File

@ -37,6 +37,15 @@ class Namespace(MutableMapping):
raise KeyError(repr(name))
return namespacify(attr)
def __setitem__(self, name: Any, value: Any) -> None:
setattr(self, name, value)
def __delitem__(self, name: Any) -> None:
try:
delattr(self, name)
except AttributeError:
raise KeyError(repr(name))
def __iter__(self) -> Iterator:
return iter(self.__dict__)
@ -49,14 +58,14 @@ class Namespace(MutableMapping):
def __str__(self) -> str:
return str(self.__dict__)
def _repr_pretty_(self, p: Any, cycle: bool) -> None:
# IPython's pretty printing
if cycle:
p.text('{}(...)'.format(self.__class__.__name__))
else:
p.text('{}('.format(self.__class__.__name__))
p.pretty(self.__dict__)
p.text(')')
def copy(self) -> 'Namespace':
return self.__class__(self.__dict__)
def __setitem__(self, name: Any, value: Any) -> None:
setattr(self, name, value)
def __delitem__(self, name: Any) -> None:
try:
delattr(self, name)
except AttributeError:
raise KeyError(repr(name))

View File

@ -34,6 +34,15 @@ class ClassRegistry(Dict[str, Callable]):
self.check(key, value)
super().__setitem__(key, value)
def _repr_pretty_(self, p: Any, cycle: bool) -> None:
# IPython's pretty printing
if cycle:
p.text('{}(...)'.format(self.__class__.__name__))
else:
p.text('{}('.format(self.__class__.__name__))
p.pretty(dict(self))
p.text(')')
@property
def metaclass(self) -> type:
class RegistryMetaclass(type):

View File

@ -1,6 +1,7 @@
from types import MappingProxyType
from typing import List, Set, Iterable, Iterator, Any
from unittest import TestCase
from unittest.mock import MagicMock, call
from objtools.collections import namespacify, Namespace
@ -69,29 +70,6 @@ class TestNamespace(TestCase):
with self.assertRaises(AttributeError):
ns.b
def test_iter(self) -> None:
ns: Namespace = Namespace(a=1, b=2)
iterator: Iterator = iter(ns)
self.assertEqual(next(iterator), 'a')
self.assertEqual(next(iterator), 'b')
def test_len(self) -> None:
self.assertEqual(len(Namespace(a=1, b=2)), 2)
self.assertEqual(len(Namespace()), 0)
def test_repr(self) -> None:
self.assertEqual(repr(Namespace()), 'Namespace({})')
self.assertEqual(repr(Namespace(a=1)), "Namespace({'a': 1})")
def test_str(self) -> None:
self.assertEqual(str(Namespace()), '{}')
self.assertEqual(str(Namespace(a=1)), "{'a': 1}")
def test_copy(self) -> None:
ns: Namespace = Namespace(a=1, b=2)
self.assertEqual(ns.copy(), ns)
self.assertIsNot(ns.copy(), ns)
def test_set(self) -> None:
ns: Any = Namespace(a=4)
ns.a = 1
@ -111,3 +89,44 @@ class TestNamespace(TestCase):
del ns.c
with self.assertRaises(KeyError):
del ns['c']
def test_iter(self) -> None:
ns: Namespace = Namespace(a=1, b=2)
iterator: Iterator = iter(ns)
self.assertEqual(next(iterator), 'a')
self.assertEqual(next(iterator), 'b')
def test_len(self) -> None:
self.assertEqual(len(Namespace(a=1, b=2)), 2)
self.assertEqual(len(Namespace()), 0)
def test_repr(self) -> None:
self.assertEqual(repr(Namespace()), 'Namespace({})')
self.assertEqual(repr(Namespace(a=1)), "Namespace({'a': 1})")
def test_str(self) -> None:
self.assertEqual(str(Namespace()), '{}')
self.assertEqual(str(Namespace(a=1)), "{'a': 1}")
def test_repr_pretty(self) -> None:
p = MagicMock(spec_set=['text', 'pretty'])
Namespace(a=1)._repr_pretty_(p, cycle=False)
self.assertEqual(p.text.call_count, 2)
self.assertEqual(p.pretty.call_count, 1)
self.assertListEqual(p.text.call_args_list, [
call('Namespace('),
call(')'),
])
self.assertEqual(p.pretty.call_args, call({'a': 1}))
def test_repr_pretty_cycle(self) -> None:
p = MagicMock(spec_set=['text', 'pretty'])
Namespace(a=1)._repr_pretty_(p, cycle=True)
self.assertEqual(p.text.call_count, 1)
self.assertFalse(p.pretty.called)
self.assertEqual(p.text.call_args, call('Namespace(...)'))
def test_copy(self) -> None:
ns: Namespace = Namespace(a=1, b=2)
self.assertEqual(ns.copy(), ns)
self.assertIsNot(ns.copy(), ns)

View File

@ -1,5 +1,5 @@
from unittest import TestCase
from unittest.mock import patch
from unittest.mock import patch, call, MagicMock
from objtools.registry import ClassRegistry
@ -61,3 +61,21 @@ class TestRegistry(TestCase):
pass
self.assertDictEqual(registry, {'foo': Thing})
def test_repr_pretty(self) -> None:
p = MagicMock(spec_set=['text', 'pretty'])
ClassRegistry(a=object)._repr_pretty_(p, cycle=False)
self.assertEqual(p.text.call_count, 2)
self.assertEqual(p.pretty.call_count, 1)
self.assertListEqual(p.text.call_args_list, [
call('ClassRegistry('),
call(')'),
])
self.assertEqual(p.pretty.call_args, call({'a': object}))
def test_repr_pretty_cycle(self) -> None:
p = MagicMock(spec_set=['text', 'pretty'])
ClassRegistry(a=object)._repr_pretty_(p, cycle=True)
self.assertEqual(p.text.call_count, 1)
self.assertFalse(p.pretty.called)
self.assertEqual(p.text.call_args, call('ClassRegistry(...)'))