[Python-modules-team] Bug#895553: sphinx: please make the set object description reproducible

Chris Lamb lamby at debian.org
Thu Apr 12 15:54:13 BST 2018


Source: sphinx
Version: 1.6.7-2
Severity: wishlist
Tags: patch
User: reproducible-builds at lists.alioth.debian.org
Usertags: toolchain randomness
X-Debbugs-Cc: reproducible-bugs at lists.alioth.debian.org

Hi,

Whilst working on the Reproducible Builds effort [0], we noticed
that sphinx could generates output that is not reproducible.

In particular, the rendering of `set` objects in default arguments
and elsewhere is currently non-determinstic. For example:

    class A_Class(object):
        a_set = {'a', 'b', 'c'}

Might be rendered as any of:

     {'a', 'b', 'c'}
     {'a', 'c', 'b'}
     {'b', 'a', 'c'}
     {'b', 'c', 'a'}
     {'c', 'a', 'b'}
     {'c', 'b', 'a'}

Patch attached that sorts the contents of sets whilst rendering.
This is parallel to the 'dict' key sorting.

 [0] https://reproducible-builds.org/


Regards,

-- 
      ,''`.
     : :'  :     Chris Lamb
     `. `'`      lamby at debian.org / chris-lamb.co.uk
       `-
-------------- next part --------------
diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py
index 7042253..774d21a 100644
--- a/sphinx/util/inspect.py
+++ b/sphinx/util/inspect.py
@@ -211,6 +211,10 @@ def object_description(object):
         else:
             items = ("%r: %r" % (key, object[key]) for key in sorted_keys)
             return "{%s}" % ", ".join(items)
+    if isinstance(object, set):
+        # Sort set contents
+        template = "{%s}" if PY3 else "set([%s])"
+        return template % ", ".join(repr(x) for x in sorted(object))
     try:
         s = repr(object)
     except Exception:
diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py
index a463f4f..fe85419 100644
--- a/tests/test_util_inspect.py
+++ b/tests/test_util_inspect.py
@@ -138,6 +138,14 @@ class TestObjectDescription(TestCase):
         description = inspect.object_description(dictionary)
         assert description == "{'a': 1, 'b': 4, 'c': 3, 'd': 2}"
 
+    def test_set_sorting(self):
+        set_ = set("gfedcba")
+        description = inspect.object_description(set_)
+        if PY3:
+            assert description == "{'a', 'b', 'c', 'd', 'e', 'f', 'g'}"
+        else:
+            assert description == "set(['a', 'b', 'c', 'd', 'e', 'f', 'g'])"
+
     def test_dict_customtype(self):
         class CustomType(object):
             def __init__(self, value):


More information about the Python-modules-team mailing list