Python types for polyglot objects#406
Conversation
…asses
Currently, this enables the registration for custom python classes that should
be associated with certain Java classes.
The registry is part of a PythonContext and is currently indexed by String keys,
which are the java class names for which python classes have been registered.
Registration takes place in a respective PolyglotModuleBuiltin and the lookup
happens in the GetClassNode#getForeign implementation.
Usage in python: `register_java_interop_type("{java_class_name}", pythonClass)`
In the future, also an annotation-style registration way should be implemented.
This enables writing lightweight python classes, which can be used for translating
between the usage of java classes "in the python way" (e.g. [] access).
Example:
```
class jArrayList(__graalpython__.ForeignType):
# Python world wants to use .append(...) as usual
def append(self, element):
# Java ArrayList only knows .add(...), we need to derive from Foreign
# in order to be able to reroute the message to the original java object
self.add(element)
register_java_interop_type("java.util.ArrayList", jList)
```
The last line corresponds to the prior commit which introduced the
`register_java_interop_type` function.
|
Thank you for your pull request and welcome to our community! To contribute, please sign the Oracle Contributor Agreement (OCA). To sign the OCA, please create an Oracle account and sign the OCA in Oracle's Contributor Agreement Application. When signing the OCA, please provide your GitHub username. After signing the OCA and getting an OCA approval from Oracle, this PR will be automatically updated. If you are an Oracle employee, please make sure that you are a member of the main Oracle GitHub organization, and your membership in this organization is public. |
|
Thank you for signing the OCA. |
|
@Sowasvonbot will integrate this in the next months. |
|
Thank you for your contribution! |
This PR was developed during the seminar "Softwaredesign" at the Hasso-Plattner Institute Potsdam
Authors: @Olliwehr, @antonykamp
Supervisors: @timfel @JensLincke
What did we change?
This PR introduces the CRUD operations for a register of Python types as equivalents for Java classes.
In the following example, we want to use instances of
java.util.ArrayListin the Python code. To have a Python idiomatic interface, we register withpolyglot.register_java_interop_typeor@polyglot.java_interop_type, a Python typejlistequivalent tojava.util.ArrayList.We used the existing interoperability extension API as reference.
New operations
We introduced CRUD operations to insert, update, delete, and get mappings and integrated the first three operations into the polyglot module.
Register type mappings with
polyglot.register_java_interop_type(javaClassNameAsString, pythonType)or@polyglot.java_interop_type(javaClassNameAsString).Edit mappings by calling the same function and passing the flag
overwrite=True. Otherwise, when registering the same java class two times, it'll throw an ErrorINTEROP_TYPE_ALREADY_REGISTERED.Remove a mapping by calling
remove_java_interop_type(javaClassNameAsString). If the class is not registered, it will throw an ErrorINTEROP_TYPE_NOT_REGISTERED.Whenever we call
getClassNode, we look for a registered type for the class. Alternatively, we returnForeign.How did we change it?
We introduced a
WeakHashMapin the Python context. In the map, the keys are string representations of the Java classes, and the values are Python types. IngetClassNode,we look the Java classes up in the map. If the key is not found, we returnForeignTypeas the default Python type.Additionally, we introduced:
register_java_interop_typefunction,java_interop_typedecorator andremove_java_interop_typefunctionto the polyglot module.
Future work
We identified two possible future work items:
Support multi-inheritance in Python types
In Python types, e.g.,
list, some functions are based on "base functions." The "base function" is building the base for other functions. It would be helpful to inherit from these types, implement the "base function" and get some tasks for free:Currently, that's not possible. We receive a "Layout Conflict Error" because
ForeignTypehas some predefined attributes and functions.We recommend splitting
ForeignTypeinto:ForeignTypewith the current behavior andForeignTypeBasewithout the predefined attributes and functions.If we'd inherit from
ForeignTypeBaseandlistnow, we probably wouldn't receive the "Layout Conflict Error" but some functions for free.Support java interfaces
If we want the Python idiomatic interface for different list classes (ArrayList, LinkedList, etc.), we'd register (and unregister) the same Python type repeatedly.
The idea is that we only register a
jlisttype for the interfacejava.util.List, and it's applied to ArrayList, LinkedList, and... by default.