Add 'patch_with_metaclass' which provides a more complete interface for supporting metaclass-based classes across Python versions.

#12 Merged at 8527c09
Repository
Deleted repository
Branch
default (fb50300a852f)
Repository
six
Branch
default
Author
  1. Jason R. Coombs
Reviewers
Description

I was working on porting a metaclass-based implementation to a unified Python 2/3 code base, but found I couldn't readily use with_metaclass to support a unified code base without altering the class hierarchy. Here is the code where I encountered the issue. Using with_metaclass would have required another base class between object and Command, which complicates the implementation and the patch. Instead patch_with_metaclass reconstructs the class using the original class as a template.

Comments (3)

  1. Jason R. Coombs author

    I've added a few tests to the pull request, including a test that captures a failure I encountered where an instance of the patched class fails to have a __dict__ attribute. I don't yet fully comprehend the reason why setting the __dict__ attribute on the class causes the instance to have no __dict__ attribute, but I assume it's some implementation detail, and this technique seems to work. Should the patcher also remove __module__ and __doc__?

  2. Benjamin Peterson repo owner

    This is pretty nice. It does have the slightly non-intuitive effect that the class is created without the metaclass first. This might cause problems if the parent has a metaclass that is a superclass of the metaclass used with the decorator. That's also quite rare, so it can probably be ignored.

    In the decorator, you will also need to remove anything that appears in __slots__. (Please add a test for a slotted class.) __module__ and __doc__ can be left alone.

    Formal documentation in document/index.rst needs to be written. Put it be six.with_metaclass, so people can compare.