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.

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 Object subclass: #GtRemotePhlowDeclarativeTestInspectable instanceVariableNames: 'string collectionOfObjects' classVariableNames: '' package: 'GToolkit-RemotePhlow-Examples' 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