Debugging remote Python views
This is a technical page that explains how to programmatically set up Remote Phlow for the PythonBridge for the purpose of development and debugging Python views. It shows the steps involved and gives you handles to participating objects.
Please refer to Inspecting remote objects using Remote Phlow and the related pages Using a simulation for inspecting objects and Specifications and Views in Remote Phlow. The page Debugging remote GemStone views was the template for this page.
First make sure you have a working PythonBridge by inspecting a simple expression.
2**32
Now we define a Python equivalent of a test object that exist in Pharo/Gemstone, namely GtRemotePhlowDeclarativeTestInspectable
which is an example object holding some data and showing some gtViews. Here is its definition that you can load/execute.
from gtoolkit_bridge import gtView class GtRemotePhlowDeclarativeTestInspectable: def __init__(self): super().__init__() self.collection = [42, "Lorem ipsum dolor sit amet", 3.14159, True, False, None] self.string = "Hello GT World !" def get_collection(self): return self.collection def get_string(self): return self.string @gtView def gtViewCollection(self, builder): clist = builder.columnedList() clist.title('Collection') clist.priority(25) clist.items(lambda: list(range(0, len(self.get_collection())))) clist.column('#', lambda index: index) clist.column('item', lambda index: str(self.get_collection()[index])) clist.set_accessor(lambda index: self.get_collection()[index]) return clist @gtView def gtViewString(self, builder): editor = builder.textEditor() editor.title("String") editor.priority(35) editor.setString(self.get_string()) return editor @gtView def gtViewError(self, builder): raise Exception("I'm sorry, Dave. I'm afraid I can't do that.") @gtView def gtViewEmpty(self, builder): return builder.empty() @gtView def gtViewCollectionForward(self, builder): forward = builder.forward() forward.title("Collection forward") forward.priority(30) forward.object(lambda: self) forward.view('gtViewCollection') return forward
With this class defined, we can instanciate it and see the views in action. Notice there are 3 views, String, Collection and Collection forward. The empty view is skipped.
GtRemotePhlowDeclarativeTestInspectable()
To get under the hood, we define remoteInspectorProxy
at the Python side as our GtRemotePhlowDeclarativeTestInspectable instance wrapped inside a GtViewedObject which is a helper to set up the views on the GT side.
from gtoolkit_bridge import GtViewedObject remoteInspectorProxy = GtViewedObject(GtRemotePhlowDeclarativeTestInspectable())
Notice how directly inspecting this gives us a double wrapper as compared to the direct instance. Let's grab remoteInspectorProxy
directly and assign it to inspectorProxy
in GT.
inspectorProxy := PBCommandStringFactory new application: PBApplication uniqueInstance; resultExpression: 'remoteInspectorProxy'; sendAndWait
We can now ask the same questions as the Remote Phlow infrastructure would.
inspectorProxy getDeclarativeViewMethodNames
inspectorProxy getViewsDeclarations
List views
listViewProxy := inspectorProxy getDeclarativeViewFor: #gtViewCollection
listViewProxy retrieveItems: 3 fromIndex: 1
listViewProxy retriveSentItemAt: 1
Forward views
Interacting with a proxy for the view
forwardViewProxy := inspectorProxy getDeclarativeViewFor: #gtViewCollectionForward
forwardViewSpecificationData := forwardViewProxy retrieveViewSpecificationForForwarding
localForwardViewSpecification := GtPhlowViewSpecification fromDictionary: forwardViewSpecificationData
Interacting with a local specification
forwardViewSpecificationData := inspectorProxy getViewDeclaration: #gtViewCollectionForward
localForwardViewSpecification := GtPhlowViewSpecification fromDictionary: forwardViewSpecificationData
localForwardViewSpecification initializeFromInspector: inspectorProxy
targetListViewSpecification := localForwardViewSpecification loadViewSpecificationForForwarding