提交 3d41ea15 编写于 作者: C Cleber Rosa

avocado/core/tree.py: allow MuxTreeNode to be hashed under Python 3

Under Python 3, as in Python 2, most objects are automatically
hashable.  Example:

   >>> class Foo(object):
   >>>     pass
   >>> hash(Foo())
   >>> 8760583602380

But if an object that implements __eq__ also has to implement
__hash__.  Under Python 3:

   >>> class Foo(object):
   >>>     def __eq__(self, other):
   >>>         return False
   Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   TypeError: unhashable type: 'Foo'

Since TreeNode implements __eq__, under Python 3, it *must* implement
__hash__.  There are a few tricky points, though.  One of them is that
"The only required property is that objects which compare equal have
the same hash value".  TreeNodes have a very flexible equality
comparison, which cannot be taken into account in a hash
implementation which doesn't have access to the "other" object.

To the best of my knowledge, the way to go with the TreeNode __hash__
implementation is to take into account the comparison of all
attributes that are used on __eq__ (name, values, children) and use
those as the composition for __hash__, as suggested by the Python
docs.  Unfortunately, some of the content of "values" and "children"
may themselves be unshashable values (such as dicts coming from YAML
test suite loader).  My coward's way out here was to use a string
representation of such unhashable types to compose the TreeNode hash.

This fixes 5 unittests of the varianter_yaml_to_mux plugin when
run under Python 3, such as:

    ======================================================================
    ERROR: test_get_rel_path (tests.test_mux.TestAvocadoParams)
    ----------------------------------------------------------------------
      ....
        if len(set([_[1] for _ in ret])) == 1:  # single source of results
    TypeError: unhashable type: 'MuxTreeNode'

Reference: https://docs.python.org/3/reference/datamodel.html#object.__hash__Signed-off-by: NCleber Rosa <crosa@redhat.com>
上级 27656da5
......@@ -200,6 +200,21 @@ class TreeNode(object):
""" Inverted eq """
return not self == other
def __hash__(self):
values = []
for item in self.value:
try:
values.append(hash(item))
except TypeError:
values.append(hash(str(item)))
children = []
for item in self.children:
try:
children.append(hash(item))
except TypeError:
children.append(hash(str(item)))
return hash((self.name, ) + tuple(values) + tuple(children))
def fingerprint(self):
"""
Reports string which represents the value of this node.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册