__new__ does not receive an instance as its first parameter. How can this happen when (a) it is a static method, as you noticed, and (b) its task is to create an instance and return it! The first parameter __new__ conditionally called cls , since it is a class.
Because of what, the error message you specify is very strange; this is usually an error message that you will get when you call an unrelated method (i.e. what you get by referring to ClassName.methodName ) with something other than an instance of this class, as a self parameter. However, staticmethods (including __new__ ) do not become unrelated methods, they are just simple functions that are class attributes:
>>> class Foo(object): def __new__(cls, *args, **kwargs): return object.__new__(cls) def method(self): pass >>> class Bar(object): pass >>> Foo.method <unbound method Foo.method> >>> Foo.__new__ <function __new__ at 0x0000000002DB1C88> >>> Foo.method(Bar()) Traceback (most recent call last): File "<pyshell#36>", line 1, in <module> Foo.method(Bar()) TypeError: unbound method method() must be called with Foo instance as first argument (got Bar instance instead) >>> Foo.__new__(Bar) <__main__.Bar object at 0x0000000002DB4F28>
From this, you can verify that __new__ should never be an unrelated method. In addition (as opposed to the usual method), you do not care that you agree on what you transmit; I managed to create an instance of Bar by calling Foo.__new__ , because both he and Bar.__new__ were ultimately implemented the same way (putting aside all the actual work to object.__new__ ).
However, this led me to a brief summary of the source code for Django itself. The Django Model class has a metaclass, ModelBase . This is quite complicated, and I did not understand what he was doing completely, but I noticed something very interesting.
ModelBase.__new__ (metaclass __new__ , which is the function that creates the class at the end of your class block) calls its super __new__ without passing its class dictionary . Instead, it passes the dictionary only with the __module__ attribute __module__ . Then, after doing a whole bunch of processing, he does the following:
# Add all attributes to the class. for obj_name, obj in attrs.items(): new_class.add_to_class(obj_name, obj)
( attrs is a dictionary containing all of your definitions in your class block, including your __new__ function; add_to_class is a metaclass method that is basically just setattr ).
Now I'm 99% sure that the problem is here because __new__ is a strange implicitly static method. Therefore, unlike any other static method, you did not apply the staticmethod decorator to it. Python (at some level) simply recognizes the __new__ method and treats it as a static method, not a regular method [1]. But I bet that this only happens when __new__ defined in a class block, and not when it is set using setattr .
Thus, your __new__ , which should be a static method, but not processed by the staticmethod staticmethod , is converted to a regular instance method. Then, when Python calls it passing the class Test , according to the protocol for creating a regular instance, it complains that it does not receive an instance of Test .
If all this is correct, then:
- This is not so because Django is a bit broken, but only in that it does not take into account Python inconsistency about
__new__ , static in mind. - Perhaps you could do this work by applying
@staticmethod to your __new__ method, although you don't need to.
[1] I think this is Python's historical quirk, since __new__ was introduced before the staticmethod decorator, but __new__ could not take an instance, since there wasnβt to call it.