Comment 6 for bug 1825435

Jay Pipes (jaypipes) wrote :

Matt, could this patch have anything to do with this you think?

It's changing out the base class for ConfigOpts and GroupAttr. When I looked at the implementations in Python2 and Python3.7, I noticed there were some differences in how the base classes that comprise "calculate" attributes.

In the case of Python2, there is a _hasattr() module-level function that is used to determine if a particular attribute *or* method exists. For example, one of the base metaclasses that collections.Mapping derives from is Container, which uses this _hasattr() function to determine if the subclass overrides the __contains__ magic method:

    def __subclasshook__(cls, C):
        if cls is Container:
            if _hasattr(C, "__contains__"):
                return True
    return NotImplemented

Compare this to the Python3.7 Container class's similar implementation:

    def __subclasshook__(cls, C):
        if cls is Container:
            return _check_methods(C, "__contains__")
    return NotImplemented

If we look at Python2's _hasattr() compared to Python3.7's _check_methods() function, we see some differences:


def _hasattr(C, attr):
        return any(attr in B.__dict__ for B in C.__mro__)
    except AttributeError:
        # Old-style class
    return hasattr(C, attr)

Python 3.7:

def _check_methods(C, *methods):
    mro = C.__mro__
    for method in methods:
        for B in mro:
            if method in B.__dict__:
                if B.__dict__[method] is None:
                    return NotImplemented
            return NotImplemented
    return True

Given the stacktrace that seems to be occurring, I think it might be worthwhile to revert and see if that might indeed be the culprit here.

Just a thought,