Skip to content

Commit

Permalink
added types to pretty printer
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan committed May 12, 2021
1 parent 201fe91 commit 410a06e
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 8 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Added syntax for call, i.e. "Foo(bar)"
- Fixed initial blank lines removed from Syntax https://github.com/willmcgugan/rich/issues/1214
- Added Console.measure as a convenient alias for Measurement.get
- Added support for pretty printing attrs objects
- Added mappingproxy to pretty print
- Added UserDict and UserList support to pretty printer

### Changed

- Changed colorama init to set strip=False
- Changed highlighter for False, True, None to not match in the middle of a word. i.e. NoneType is no longer highlighted as None

### Fixed

- Fixed initial blank lines removed from Syntax https://github.com/willmcgugan/rich/issues/1214

## [10.1.0] - 2020-04-03

Expand Down
2 changes: 1 addition & 1 deletion rich/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ def detect_legacy_windows() -> bool:
if detect_legacy_windows(): # pragma: no cover
from colorama import init

init()
init(strip=False)


class Console:
Expand Down
2 changes: 1 addition & 1 deletion rich/highlighter.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class ReprHighlighter(RegexHighlighter):
r"(?P<eui64>(?:[0-9A-Fa-f]{1,2}-){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){3}[0-9A-Fa-f]{4})",
r"(?P<eui48>(?:[0-9A-Fa-f]{1,2}-){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})",
r"(?P<call>[\w\.]*?)\(",
r"(?P<bool_true>True)|(?P<bool_false>False)|(?P<none>None)",
r"\b(?P<bool_true>True)\b|\b(?P<bool_false>False)\b|\b(?P<none>None)\b",
r"(?P<ellipsis>\.\.\.)",
r"(?P<number>(?<!\w)\-?[0-9]+\.?[0-9]*(e[\-\+]?\d+?)?\b|0x[0-9a-fA-F]*)",
r"(?P<path>\B(\/[\w\.\-\_\+]+)*\/)(?P<filename>[\w\.\-\_\+]*)?",
Expand Down
20 changes: 16 additions & 4 deletions rich/pretty.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
import os
import sys
from array import array
from collections import Counter, defaultdict, deque
from collections import Counter, defaultdict, deque, UserDict, UserList
from dataclasses import dataclass, fields, is_dataclass
from itertools import islice
from typing import (
Mapping,
TYPE_CHECKING,
Any,
Callable,
Expand All @@ -17,6 +18,7 @@
Union,
Tuple,
)
from types import MappingProxyType

try:
import attr as _attr_module
Expand Down Expand Up @@ -264,13 +266,16 @@ def _get_braces_for_array(_object: array) -> Tuple[str, str, str]:
Counter: lambda _object: ("Counter({", "})", "Counter()"),
deque: lambda _object: ("deque([", "])", "deque()"),
dict: lambda _object: ("{", "}", "{}"),
UserDict: lambda _object: ("{", "}", "{}"),
frozenset: lambda _object: ("frozenset({", "})", "frozenset()"),
list: lambda _object: ("[", "]", "[]"),
UserList: lambda _object: ("[", "]", "[]"),
set: lambda _object: ("{", "}", "set()"),
tuple: lambda _object: ("(", ")", "()"),
MappingProxyType: lambda _object: ("mappingproxy({", "})", "mappingproxy({})"),
}
_CONTAINERS = tuple(_BRACES.keys())
_MAPPING_CONTAINERS = (dict, os._Environ)
_MAPPING_CONTAINERS = (dict, os._Environ, MappingProxyType, UserDict)


def is_expandable(obj: Any) -> bool:
Expand Down Expand Up @@ -592,7 +597,12 @@ def iter_attrs() -> Iterable[

pop_visited(obj_id)

elif obj_type in _CONTAINERS:
elif isinstance(obj, _CONTAINERS):
for container_type in _CONTAINERS:
if isinstance(obj, container_type):
obj_type = container_type
break

obj_id = id(obj)
if obj_id in visited_ids:
# Recursion detected
Expand All @@ -601,7 +611,9 @@ def iter_attrs() -> Iterable[

open_brace, close_brace, empty = _BRACES[obj_type](obj)

if obj:
if obj_type.__repr__ != type(obj).__repr__:
node = Node(value_repr=to_repr(obj), last=root)
elif obj:
children = []
node = Node(
open_brace=open_brace,
Expand Down
20 changes: 19 additions & 1 deletion tests/test_pretty.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from array import array
from collections import defaultdict
from collections import defaultdict, UserDict, UserList
from dataclasses import dataclass, field
import io
import sys
Expand Down Expand Up @@ -229,3 +229,21 @@ class Foo:
print(repr(result))
expected = "Foo(bar=AttributeError('bar'))"
assert result == expected


def test_user_dict():
class D1(UserDict):
pass

class D2(UserDict):
def __repr__(self):
return "FOO"

d1 = D1({"foo": "bar"})
d2 = D2({"foo": "bar"})
result = pretty_repr(d1, expand_all=True)
print(repr(result))
assert result == "{\n 'foo': 'bar'\n}"
result = pretty_repr(d2, expand_all=True)
print(repr(result))
assert result == "FOO"

0 comments on commit 410a06e

Please sign in to comment.