mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2026-08-11 13:34:59 -05:00
object inspection: produce deterministic descriptions for nested collection datastructures (#11312)
``util.inspect.object_description`` already attempts to sort collections, but this can fail. This commit handles the failure case by using string-based object descriptions as a fallback deterministic sort ordering, and protects against recursive collections. Co-authored-by: Chris Lamb <lamby@debian.org> Co-authored-by: Faidon Liambotis <paravoid@debian.org> Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
This commit is contained in:
co-authored by
Chris Lamb
Faidon Liambotis
Adam Turner
parent
7d16dc0cac
commit
467e94dc62
@@ -503,10 +503,32 @@ def test_set_sorting():
|
||||
assert description == "{'a', 'b', 'c', 'd', 'e', 'f', 'g'}"
|
||||
|
||||
|
||||
def test_set_sorting_enum():
|
||||
class MyEnum(enum.Enum):
|
||||
a = 1
|
||||
b = 2
|
||||
c = 3
|
||||
|
||||
set_ = set(MyEnum)
|
||||
description = inspect.object_description(set_)
|
||||
assert description == "{MyEnum.a, MyEnum.b, MyEnum.c}"
|
||||
|
||||
|
||||
def test_set_sorting_fallback():
|
||||
set_ = {None, 1}
|
||||
description = inspect.object_description(set_)
|
||||
assert description in ("{1, None}", "{None, 1}")
|
||||
assert description == "{1, None}"
|
||||
|
||||
|
||||
def test_deterministic_nested_collection_descriptions():
|
||||
# sortable
|
||||
assert inspect.object_description([{1, 2, 3, 10}]) == "[{1, 2, 3, 10}]"
|
||||
assert inspect.object_description(({1, 2, 3, 10},)) == "({1, 2, 3, 10},)"
|
||||
# non-sortable (elements of varying datatype)
|
||||
assert inspect.object_description([{None, 1}]) == "[{1, None}]"
|
||||
assert inspect.object_description(({None, 1},)) == "({1, None},)"
|
||||
assert inspect.object_description([{None, 1, 'A'}]) == "[{'A', 1, None}]"
|
||||
assert inspect.object_description(({None, 1, 'A'},)) == "({'A', 1, None},)"
|
||||
|
||||
|
||||
def test_frozenset_sorting():
|
||||
@@ -518,7 +540,39 @@ def test_frozenset_sorting():
|
||||
def test_frozenset_sorting_fallback():
|
||||
frozenset_ = frozenset((None, 1))
|
||||
description = inspect.object_description(frozenset_)
|
||||
assert description in ("frozenset({1, None})", "frozenset({None, 1})")
|
||||
assert description == "frozenset({1, None})"
|
||||
|
||||
|
||||
def test_nested_tuple_sorting():
|
||||
tuple_ = ({"c", "b", "a"},) # nb. trailing comma
|
||||
description = inspect.object_description(tuple_)
|
||||
assert description == "({'a', 'b', 'c'},)"
|
||||
|
||||
tuple_ = ({"c", "b", "a"}, {"f", "e", "d"})
|
||||
description = inspect.object_description(tuple_)
|
||||
assert description == "({'a', 'b', 'c'}, {'d', 'e', 'f'})"
|
||||
|
||||
|
||||
def test_recursive_collection_description():
|
||||
dict_a_, dict_b_ = {"a": 1}, {"b": 2}
|
||||
dict_a_["link"], dict_b_["link"] = dict_b_, dict_a_
|
||||
description_a, description_b = (
|
||||
inspect.object_description(dict_a_),
|
||||
inspect.object_description(dict_b_),
|
||||
)
|
||||
assert description_a == "{'a': 1, 'link': {'b': 2, 'link': dict(...)}}"
|
||||
assert description_b == "{'b': 2, 'link': {'a': 1, 'link': dict(...)}}"
|
||||
|
||||
list_c_, list_d_ = [1, 2, 3, 4], [5, 6, 7, 8]
|
||||
list_c_.append(list_d_)
|
||||
list_d_.append(list_c_)
|
||||
description_c, description_d = (
|
||||
inspect.object_description(list_c_),
|
||||
inspect.object_description(list_d_),
|
||||
)
|
||||
|
||||
assert description_c == "[1, 2, 3, 4, [5, 6, 7, 8, list(...)]]"
|
||||
assert description_d == "[5, 6, 7, 8, [1, 2, 3, 4, list(...)]]"
|
||||
|
||||
|
||||
def test_dict_customtype():
|
||||
|
||||
Reference in New Issue
Block a user