Search code examples
pythonc++factoryboost-pythonderived-class

Create a derived class from a boost-python wrapped factory


In a C++ library I have a class with private constructors and a factory:

class MyServer {
    MyServer() {..};
  public:
    MyServer create(std::string &config);
};

With boost-python I create a wrapper which lets me use this factory:

from MyWrappedLibrary import MyServer, StartServer
server = MyServer.create('some: magic, config: string')
StartServer(server)

Now I want to add a method to MyServer like this:

from MyWrappedLibrary import MyServer, StartServer

class MyEnhancedServer(MyServer):
    def __init__(self, config):
        super().__init__(config)

    def another_method(self):
        do(something)

But of course this does not work since I can't instantiate MyServer directly.

Of course I could create a class which doesn't derive from MyServer but it would not feel good since I had to wrap every method:

class MyEnhancedServer:
    def __init__(self, config):
        self.core_instance = MyServer.create(config)

    def foo_1(self):  # wrapper
        self.core_instance.foo_1()

    def foo_2(self):  # wrapper
        return self.core_instance.foo_2()

    def another_method(self):
        do(something)

server = MyEnhancedServer('some: magic, config: string')
StartServer(server.core_instance)

Question: Is there a way to make the result of MyServer.create() the 'base instance' of MyEnhancedServer?

The result would be something like this:

class MyEnhancedServer(MyServer):
    def __init__(self, config):
        self.MyServer = MyServer.create()

    def another_method(self):
        do(something)

Solution

  • A colleague told me how to do it but would not post an answer. The trick is to implement __new__() and set the instance' class with this cool magic:

    class MyEnhancedServer(MyServer):
        def __new__(cls, config):
            self = cls.create(config)
            self.__class__ = cls.__class__(cls.__name__, (cls, ), {})
            return self