import filters - TypeError: type() doesn't support MRO entry resolution

Viewed 973

Python 3.7.1, filters 1.3.2

>>> import filters
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "E:\anaconda3\lib\site-packages\filters\__init__.py", line 27, in <modu
    from filters.extensions import FilterExtensionRegistry
  File "E:\anaconda3\lib\site-packages\filters\extensions.py", line 11, in <mo
    from class_registry import EntryPointClassRegistry
  File "E:\anaconda3\lib\site-packages\class_registry\__init__.py", line 5, in
    from .registry import *
  File "E:\anaconda3\lib\site-packages\class_registry\registry.py", line 33, i
    class BaseRegistry(with_metaclass(ABCMeta, Mapping)):
  File "E:\anaconda3\lib\site-packages\six.py", line 827, in __new__
    return meta(name, bases, d)
  File "E:\anaconda3\lib\abc.py", line 126, in __new__
    cls = super().__new__(mcls, name, bases, namespace, **kwargs)
TypeError: type() doesn't support MRO entry resolution; use types.new_class()

Looks like it is related to this and got fixed. However, I have the latest Python 3.7 and filters package. Any ideas?

1 Answers

Maintainer of filters and class-registry here. I apologise that it took me so long to find this!

The issue is caused by a couple of lines in the class-registry package:

class BaseRegistry(with_metaclass(ABCMeta, Mapping)):
    ...

class MutableRegistry(with_metaclass(ABCMeta, BaseRegistry)):
    ...

The error occurs because with_metaclass() creates a dynamic type internally, which conflicts when using it with a generic type like Mapping and MutableMapping.

This issue was discussed on https://bugs.python.org/issue33188 and it appears that the outcome was, "works as intended":

This is not a bug but an explicit design decision. Generic classes are static typing concept and therefore are not supposed to work freely with dynamic class creation. During discussion of PEP 560 it was decided that there should be at least one way to dynamically create generic classes, types.new_class was chosen for this, see https://www.python.org/dev/peps/pep-0560/#dynamic-class-creation-and-types-resolve-bases

Also the exception message is quite clear about this. Unfortunately, PEPs 560 and 557 were discussed in parallel so not every possible interactions where thought out. But is it critical for dataclasses to call type? I believe there should be no other differences with types.new_class. I would say the latter is even better than type because it correctly treats __prepare__ on the metaclass IIRC. So I would propose to switch from type() to types.new_class() for dynamic creation of dataclasses.

There are two possible ways to resolve this issue:

  1. Use add_metaclass() instead of with_metaclass().
  2. Drop support for Python 2 and replace with_metaclass() with Python-3-style base/metaclass declarations.

Both solutions are represented in pull requests submitted by stj.

I no longer work at EFL Global [now LenddoEFL], so I don't have direct access to that repo any more. It may be some time before a new version is released; in the meantime, I have forked the project and released a new version that explicitly supports Python 3.7 (and drops support for Python 2):

https://pypi.org/project/phx-filters/

Related