Python4Capella: why do certain methods listed in the docs not work the same way as others?

I would like to export a list of all my model CapellaElements with their element types.

In the “Python4Capella Simplified Metamodel” file I downloaded the following methods are listed for CapellaElements:
image
so I tried the first 2.
The first one works fine, but the second one gives me the following error:

org.eclipse.ease.ScriptExecutionException: Traceback (most recent call last):
File “workspace://Python4Capella/FMEA-in-ARCADIA-scripts/test.py”, line 52, in
_pyease_builtins = builtins
^^^^^^
File “workspace://Python4Capella/simplified_api/capella.py”, line 250, in get_element_type
def getResult(self):
^^^^^^^^^^^^^^^^^
AttributeError: TODO

Any hints as to why this might be?
Also the function is defined in the capella.py file as:

def get_element_type(self) -> str:
    """
    Returns: String
    """
    raise AttributeError("TODO")

Thank you

The method get_element_type is not implemented but you can use the following Java API:

my_element.get_java_object().eClass().getName()

you can also get the EPackage nsURI if needed:

my_element.get_java_object().eClass().getEPackage().getNsURI()

You can also use the Python type() method:

type(my_element)
1 Like

Thank you very much, Yvan.

Just to make sure I understand: is that the case also with the get_related_activity_function() method?
There, I get this error:

org.eclipse.ease.ScriptExecutionException: Traceback (most recent call last):
  File "workspace://Python4Capella/--scripts/test3.py", line 55, in <module>
    def _pyease_patch_builtins(name, value):
                         ^^^^^^^^^^^^^^^^^^^^
  File "workspace://Python4Capella/simplified_api/capella.py", line 2810, in get_related_activity_function
  File "C:\Users\cd454\Downloads\capella-6.1.0.202303291413\capella\plugins\py4j-python_0.10.9.5-bnd-2odeag\src\py4j\java_gateway.py", line 1321, in __call__
    return_value = get_return_value(
                   ^^^^^^^^^^^^^^^^^
  File "C:\Users\cd454\Downloads\capella-6.1.0.202303291413\capella\plugins\py4j-python_0.10.9.5-bnd-2odeag\src\py4j\protocol.py", line 330, in get_return_value
    raise Py4JError(
py4j.protocol.Py4JError: An error occurred while calling o2652.getRelatedActivityFunction. Trace:
py4j.Py4JException: Method getRelatedActivityFunction([]) does not exist
	at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318)
	at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:326)
	at py4j.Gateway.invoke(Gateway.java:274)
	at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
	at py4j.commands.CallCommand.execute(CallCommand.java:79)
	at py4j.ClientServerConnection.sendCommand(ClientServerConnection.java:244)
	at py4j.CallbackClient.sendCommand(CallbackClient.java:384)
	at py4j.CallbackClient.sendCommand(CallbackClient.java:356)
	at py4j.reflection.PythonProxyHandler.invoke(PythonProxyHandler.java:106)
	at jdk.proxy11/jdk.proxy11.$Proxy24.executeScript(Unknown Source)
	at org.eclipse.ease.lang.python.py4j.internal.Py4jScriptEngine.internalExecute(Py4jScriptEngine.java:240)
	at org.eclipse.ease.lang.python.py4j.internal.Py4jScriptEngine.execute(Py4jScriptEngine.java:227)
	at org.eclipse.ease.AbstractScriptEngine.inject(AbstractScriptEngine.java:189)
	at org.eclipse.ease.AbstractScriptEngine.run(AbstractScriptEngine.java:242)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

Is there a general method to find out when a function is not implemented, and to navigate to the Java method which can replace it?

Also on a more general note: is it possible to control Capella by writing Java code directly, and is it feasible for non-professional programmers (like myself) who cannot figure these things out on their own?

Thank you

Some methods are not implemented and raise an exception:

raise AttributeError("TODO")

Others are implemented in a generic way (generated) and might not match the Java API. This is the case for StateFragment.get_related_activity_function(). The stack state that the Java method getRelatedActivityFunction() doesn’t exists.

From here you can open the StateFragment Java class in a Java editor or from the source code. The name of the Java method is getRelatedAbstractFunction().

You can replace the call in the Python API:

    def get_related_activity_function(self) -> AbstractActivityFunction:
        """
        Returns: AbstractActivityFunction[0..1]
        """
        value =  self.get_java_object().getRelatedAbstractFunction()
        if value is None:
            return value
        else:
            e_object_class = getattr(sys.modules["__main__"], "EObject")
            specific_cls = e_object_class.get_class(value)
            return specific_cls(value)

I opened the following issue:

Thant you for your feedback.

1 Like

Thank you for this explanation.
I think I found another instance of different method naming in capella.py: in the class “SequenceMessage”, method “get_invoked_exchange”, the reference to “getInvokedExchange” fails, while it works with “getInvokedOperation”.

When I cannot locate a .java file, for example in the case of “BehaviorPC”, I do not know where to look though, like for example in the case of the function “get_outgoing_component_exchanges” of the class “BehavioralComponent”.
Could you help me out with this case too?
Many thanks!

1 Like

Thank you I opened the following issue:

One other way to get this information can be through the Sirius interpreter. You can select an element from the Capella model and use CTRL+SPACE to trigger the content assist in the interpreter view. It will list all features from the selected object, then you can addapt them with ‘get’ or ‘set’ to call them in your Python code. If you select the element from a diagram you will have the diagram element selected , you should add a .target in the interpreter to get the semantic element (Capella element).

The BehaviorPC is a PhysicalComponent in the Java API. You can check the Python constructor:

class BehaviorPC(PhysicalComponent, BehavioralComponent):
    """
    System component in charge of implementing / realizing some of the functions devoted to the system
    """
    e_class = get_e_classifier("http://www.polarsys.org/capella/core/pa/" + capella_version(), "PhysicalComponent")

So you can have access to all EStructuralFeature of the PhysicalComponent EClass.

In the case of the BehavioralComponent There is no corresponding class in the Java API but all component classes extend it. You can use the F4 shortcut to show the type hierarchy of a Python (or Java) class:
image

So depending on the instance of BehavioralComponent you have you can check its Java class. You can try to call the getOwnedComponentExchanges() Java method.
I opened an issue:

1 Like

Hello and thanks again,

the method getOwnedComponentExchanges() was also the only one I found by searching. Unfortunately, it only returns ComponentExchanges which connect the BehaviorPC to its child BehaviorPCs.

Also, I was not able to get any elements to show in the interpreter view. Does that require a specific perspective? I did not manage to do this fetching and adapting with “get” and “set” you were proposing.

Maybe you need to get the owned component exchanges of the container of you component ?

For the interpreter view I typed aql:self. and I selected the PhysicalArchitecture in the project explorer then used CTRL+SPACE:

1 Like

Oooh now I got it. I was not putting my cursor in the Expression box before using the keys combination. Thank you. I will see how much gold I can extract from this new source.

1 Like