research-virtualfortknox / msb-client-websocket-python

The python client library to connect to the websocket interface of the MSB (Manufacturing Service Bus)
Apache License 2.0
5 stars 4 forks source link

Crash using bound methods as function callback #3

Closed theuser1 closed 5 years ago

theuser1 commented 5 years ago

I'm submitting a ...

Current behavior: The msb client crashes at getSelfDescription() when a function callback is bound to a object instance instead of a global method. Hence no registration to the MSB is possible.

Expected behavior: There should be no difference using static methods as callbacks or methods bound to an object (non-static).

Steps to reproduce:

  1. Create a MsbClient with a function handler using a callback of a bound method
    
    SERVICE_TYPE = "SmartObject"
    SO_UUID = str(uuid.uuid1())
    SO_NAME = "MSBClientPythonAppSample" + SO_UUID[-6:]
    SO_DESCRIPTION = "MSBClientPythonAppSample description"  
    SO_TOKEN = SO_UUID[-6:]
    myMsbClient = MsbClient(
        SERVICE_TYPE,
        SO_UUID,
        SO_NAME,
        SO_DESCRIPTION,
        SO_TOKEN,
    )

class myClass(): def myMethod(self,msg): print(str(msg))

myMsbClient = MsbClient(SERVICE_TYPE, SO_UUID,SO_NAME,SO_DESCRIPTION,SO_TOKEN,)

myInstance = myClass()

myFunction = Function("FUNCTION2", "Function2", "Function2_description", DataType.STRING, myInstance.myMethod,)

myMsbClient.addFunction(myFunction)

print(myMsbClient.objectToJson(myMsbClient.getSelfDescription()))

Or call myMsbClient.register() to call getSelfDescription indirectly

2. Observe the crash at: (Line number might be slightly off since i added debug output)

File "c:\Users\xx\Downloads\msb-client-websocket-python\test.py", line 56, in print(myMsbClient.objectToJson(myMsbClient.getSelfDescription())) File "c:\Users\xx\Downloads\msb-client-websocket-python\msb_client\MsbClient.py", line 819, in getSelfDescription del f["implementation"] KeyError: 'implementation'


**MSB client version:** 1.0.2

**Anything else:**
The issue is related to the jsonpickle library, especially jsonpickle.encode(). Static method delegates get added to the json-tree with the value "None" whilst object bound methods don't get added to the json tree at all. The key error occurs since the "implementation" (= method delegate) is not found in the json tree when using object bound methods. The following example illustrates the behaviour that only the static method delegate gets pickled:
```python
class myClass():
    def myMethod(self,msg):
        print(str(msg))

    @staticmethod
    def myStaticMethod(parameter_list):
        pass

    def __init__(self):
        self.myMethodDelegate = self.myMethod
        self.myMethodStaticDelegate = myClass.myStaticMethod

myInstance = myClass()
print(jsonpickle.encode(myInstance, unpicklable=False))
# prints { "myMethodStaticDelegate": null }

Possible fix: Check for the existence of the "implementation" key in the cloned object and remove the key only when its present.

Additional remark: Bound methods work out of the box in python with the msb client. This can be seen when calling the implementation directly (usually gets called from the websocket callback):

myMsbClient.functions["FUNCTION2"].implementation("test")
ipamaas commented 5 years ago

Thanks for reporting! Bugfix comes with release v1.0.3!