Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Define __prepare__() in with_metaclass() (#178)
Define `__prepare__()` in `with_metaclass()`'s temporary metaclass, and make sure that it passes the correct bases to the real metaclass's `__prepare__()`. The temporary metaclass previously didn't extend the `__prepare__()` method, which meant that if the real metaclass had a `__prepare__()`, it wouldn't get called correctly. This could lead to bugs in Python 3 code. The temporary metaclass's `__prepare__()` gets called with ```bases=(temporary_class,)```. Since there was no proxy in the middle, that was getting passed directly to the real metaclass's `__prepare__()`. But then, if the real class's `__prepare__()` method depended on the bases, the logic would be incorrect. This was a problem in projects that use `enum` / `enum34` and try to use `with_metaclass(EnumMeta)`. `enum34.EnumMeta` doesn't define `__prepare__()`, since it is a Python 2 backport. Python 3's `enum.EnumMeta` does define `__prepare__()`, but originally didn't depend at all on the bases. But starting in Python 3.6, `enum.EnumMeta.__prepare__()` will raise `TypeError` if the bases aren't valid for an enum subclass. Thus, a codebase that was successfully using `enum` / `enum34` and `with_metaclass(EnumMeta)` could break on Python 3.6.
- Loading branch information