mercredi 27 juillet 2016

How to avoid circular reference in python - a class member creating an object of another class and passing self as parameter?

I need some help in terms of 'pythonic' way of handling a specific scenario.

I'm writing an Ssh class (wraps paramiko) that provides the capability to connect to and executes commands on a device under test (DUT) over ssh.

class Ssh:
    def connect(some_params):
        # establishes connection
    def execute_command(command):
        # executes command and returns response
    def disconnect(some_params):
        # closes connection

Next, I'd like to create a Dut class that represents my device under test. It has other things, besides capability to execute commands on the device over ssh. It exposes a wrapper for command execution that internally invokes the Ssh's execute_command. The Ssh may change to something else in future - hence the wrapper.

def Dut:
    def __init__(some params):
        self.ssh = Ssh(blah blah)

    def execute_command(command)
        return self.ssh.execute_command(command)

Next, the device supports a custom command line interface for device under test. So, a class that accepts a DUT object as an input and exposes a method to execute the customised command.

def CustomCli:
    def __init__(dut_object):
        self.dut = dut_object
    def _customize(command):
        # return customised command
    def execute_custom_command(command):
        return self.dut.execute_command(_customize(command))

Each of the classes can be used independently (CustomCli would need a Dut object though).

Now, to simplify things for user, I'd like to expose a wrapper for CustomCli in the Dut class. This'll allow the creator of the Dut class to exeute a simple or custom command. So, I modify the Dut class as below:

def Dut:
    def __init__(some params):
        self.ssh = Ssh(blah blah)
        self.custom_cli = Custom_cli(self) ;# how to avoid this circular reference in a pythonic way?

    def execute_command(command)
        return self.ssh.execute_command(command)

    def execute_custom_command(command)
        return self.custom_cli.execute_custom_command(command)

This will work, I suppose. But, in the process I've created a circular reference - Dut is pointing to CustomCli and CustomCli has a reference to it's creator Dut instance. This doesn't seem to be the correct design. What's the best/pythonic way to deal with this?

Any help would be appreciated!

Regards

Sharad

Aucun commentaire:

Enregistrer un commentaire