Reputation: 17900
I wrote the following metaclass:
class FieldHandlerBase(type):
def __new__(cls, name, bases, dct, model):
...
return super(FieldHandlerBase, cls).__new__(cls, name, bases, dct)
Now, I try to dynamically create a class using the above metaclass:
FieldHandlerBase(
'%sFieldHandler' % name,
(FieldHandler,),
{rel_type: dct.setdefault(rel_type, ()) for rel_type in REL_TYPES},
model=name)
But it throws me this error:
> model=name)
E TypeError: Error when calling the metaclass bases
E type.__init__() takes no keyword arguments
I don't understand why, since I call the metaclass base (type
here, from within FieldHandlerBase
) with the correct number of arguments. How can I fix this? I need to pass an extra argument to FieldHandlerBase
and I don't want to include it into the dct
argument, since I need it only at metaclass level.
Upvotes: 1
Views: 1103
Reputation: 40713
You need to write an __init__
method as well as a __new__
method. Otherwise, python will call type.__init__
for your new class, which does not take any additional arguments.
eg.
class FieldHandlerBase(type):
def __init__(cls, name, bases, attrs, model):
type.__init__(cls, name, bases, attrs)
cls.model = model
def __new__(metacls, name, bases, attrs, model):
...
return type.__new__(metacls, name, bases, attrs)
class ExampleFieldHandler(FieldHandler, metaclass=FieldHandlerBase,
model="Example"):
clsvar = "var"
# or
ExampleFieldHandler = FieldHandlerBase(
"ExampleFieldHandler",
(FieldHandler,),
{"clsvar": "var"},
model="Example"
)
assert ExampleFieldHandler.model == "Example"
Upvotes: 2