name lookup failure using metaclasses with unittests

Ulrich Eckhardt ulrich.eckhardt at dominolaser.com
Thu Apr 11 02:43:58 EDT 2013


Am 10.04.2013 11:52, schrieb Peter Otten:
> Ulrich Eckhardt wrote:
[...]
> It looks like this particular invocation relies on class attribute and
> function __name__ being identical.
>
> Please file a bug report.

Thanks for confirming this and reducing the test case even more.


>> Now, concerning Python 3, it fails to detect any test case at all! My
>> guess is that the unittest library was changed to use metaclasses itself
>> in order to detect classes derived from unittest.TestCase. Therefore,
>> overriding the metaclass breaks test case discovery. My question in that
>> context is how do I extend metaclasses instead of overriding it? In
>> other words, what is the equivalent to super() for class creation?
>
> Python 3 does not recognize the __metaclass__ attribute as the metaclass.
> You need to provide it like so:
>
> def __metaclass__(name, bases, dict):
>      ...
>
> class X(unittest.TestCase, metaclass=__metaclass__):
>      pass

:|

Doing some research[0, 1] on metaclasses in 2 and 3, I have a few more 
questions...

The first thing I was wondering was why Python doesn't complain about a 
class property that is marked as special (leading and trailing double 
underscores) but that it knows nothing about. Worse, Python 3 should be 
aware of its legacy and recognize the Python 2 metaclass syntax, even if 
only to reject it loudly. I'm pretty sure there is a reason for that,

The second question that came up was if there is a way to keep a 
metaclass defined inside the class or if the only way is to provide it 
externally. The reason I like this in-class definition is that for my 
case of autogenerated test functions, everything is in one place which 
used to be in a loop that modified the class after its creation. Maybe 
I'm just too brainwashed by static languages though.

To get the Python2 feeling back, I have a hack in mind that involves 
creating a baseclass which in turn provides a metaclass that invokes a 
specific function to post-initialize the class, similar to the way 
Python 2 does it automatically, but I'm wondering if there isn't 
anything better. Also PEP 3115 "Metaclasses in Python 3000"[2] seems to 
consider postprocessing of a class definition as better handled by a 
class decorator, which is something I haven't looked at yet.

Greetings from Hamburg!

Uli


[0] http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/
[1] http://www.artima.com/weblogs/viewpost.jsp?thread=236234
[2] http://www.python.org/dev/peps/pep-3115/




More information about the Python-list mailing list