Use of metaclass python to override __init__ and instantiate the class later on I m writting some API which would use configuration-like arguments.

Here is an example configuration which will be used by my API

quail.run(
    quail.SolutionPacked(path='Allum1'),
    quail.Installer(
        name='Allum1',
        icon='icon.jpeg',
        binary='allum1',
        console=True
    ),
    quail.builder.Builder(
        quail.builder.CmdIcon('icon.ico'),
        quail.builder.CmdZip(solution_path, 'solution.zip')
    )
)


The only problem with that: we will always instantiate, even when we won't use the instance, (for example if we want to uninstall we won't use the install class)

One way around I have found is to use metaclass and override __call__ to get an "EggInstance" so I can instantiate the actual class later on.

Example implementation:

import six

class InstanceEgg:
    def __init__(self, cls, *args, **kwargs):
        self._cls = cls
        self._args = args
        self._kwargs = kwargs

    def __call__(self):
        return self._cls(_get_instance=True, *self._args, **self._kwargs)

class Egg(type):
    def __call__(cls, *args, **kwargs):
        get_instance = kwargs.pop("_get_instance", False)
        if get_instance:
            return super().__call__(*args, **kwargs)
        return InstanceEgg(cls, *args, **kwargs)

@six.add_metaclass(Egg)
class Test:
    def __init__(self, a, b):
        print("init %d %d" % (a, b))


Example use:

egg = Test(1, 2)
print("got egg")
f = egg()


Output:

got egg
init 1 2


Do you think it is acceptable to use metaclass for this purpose?

And what do you recommend?
From the looks of it you have objects that you only want to partially create, when you create them the first time.

To do this you can use functools.partial:

quail.run(
    partial(quail.SolutionPacked, path='Allum1'),
    partial(
        quail.Installer,
        name='Allum1',
        icon='icon.jpeg',
        binary='allum1',
        console=True
    ),
    partial(
        quail.builder.Builder,
        partial(quail.builder.CmdIcon, 'icon.ico'),
        partial(quail.builder.CmdZip, solution_path, 'solution.zip')
    )
)


Yeah, this isn't really that attractive. However it is what you want.

And so you can use a metaclass to perform this action automagically.
I'd remove the _get_instance stuff from your Egg, remove InstanceEgg and use a partial call.

from functools import partial


class PartialInit(type):
    def __call__(cls, *args, **kwargs):
        return partial(super().__call__, *args, **kwargs)


@six.add_metaclass(PartialInit)
class Test:
    def __init__(self, a, b):
        print('init {} {}'.format(a, b))


t = Test('a')
print('Made t: {}'.format(t))
t('b')