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.


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):
		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

	def gtViewCollection(self, builder):
		clist = builder.columnedList()
		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

	def gtViewString(self, builder):
		editor = builder.textEditor()
		return editor

	def gtViewError(self, builder):
		raise Exception("I'm sorry, Dave. I'm afraid I can't do that.")
	def gtViewEmpty(self, builder):
		return builder.empty()
	def gtViewCollectionForward(self, builder):
		forward = builder.forward()
		forward.title("Collection forward")
		forward.object(lambda: self)
		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.


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';

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