Skip to content

GSOC 2021 Summary

Hnatiuk Vladyslav edited this page Aug 22, 2021 · 1 revision

Summary

During GSoC, I worked on PyQuotient library. It is a set of Python bindings for libQuotient - C++ SDK for creating Qt-based Matrix clients. My main goal was to prove the concept, create bindings for all modules needed for a basic Matrix client, and provide a demo client showing the usage of PyQuotient.

The codebase is in this repository. It was created for GSoC and the whole work was done by me and mentored by @kitsune.

The list of tasks that were done during GSOC and should be done in future is available on our project board.

Main steps were:

Preparation work that was done before GSoC started. We decided to use Github Actions for CI to keep the toolset the same for both libQuotient and PyQuotient and make maintenance simple.

Shiboken6 tool was chosen for bindings generation as a tool officially supported and maintained by Qt. It declares good support of Qt projects, but at the same time is new and not so well tested outside of the Qt.

BaseJob is a libQuotient class used as a base for all classes in which API calls are done.

To test new elements of PyQuotient the unit-testing approach was chosen and implemented using pytest library.

To be able to work with Matrix API except *Job classes also Connection and ConnectionData are needed. At this step I implemented bindings for ConnectionData class that includes info such as userId, accessToken and similar.

In the next step first bindings for Connection class and then for elements that represent Matrix API. Matrix has API documentation in Swagger format which is well suitable for code generation. libQuotient uses its own tool gtad for this purpose that generates C++ classes for using API based on file templates. I used gtad with custom templates for the generation of bindings definitions(in shiboken it's XML files), so they are generated automatically as part of CMake build.

The result of the first milestone was the initial UI demo client. It includes the following functionality: resolve server, login (password, SSO), support of multiple accounts, logout, start data sync in background after successful login. For implementation I chose to create an application with similar structure and functionality to those Quaternion, the reference client for libQuotient. So we can be sure that all features needed for a real client work and developers have an example of their usage. PySide6 - official bindings of Qt for Python - were used to build the UI.

Events are used to get information from the server. For the core of event processing I implemented bindings for Event, RoomEvent and StateBaseEvent libQuotient classes.

The next big feature in the demo client was the room list.

One of the most complex things in Matrix client is the Timeline that displays all messages in a chat. There are many types of events, all of them have different additional information, not all fields are ready for displaying in Qt UI (for example rich messages). To save a lot of implementation efforts we decided to reuse Timeline components from Quaternion, that are implemented in QML (markup language used in Qt). QML is also supported in PySide6, but it was unclear whether it works with python bindings. We successfully validated this idea and integrated the existing Timeline QML sources in the demo client.

Challenges

There were three biggest challenges:

  1. Shiboken has many features, but documentation is not full yet, so it's not so easy to start with it. Basic aspects are covered, there are also few simple examples, but all other information I got by analyzing PySide6 source code, binding definitions of Qt.

  2. Shiboken is used in production only for Qt bindings. It works well for the implementation of Qt itself, was developed exactly for it, but if library has other constructions, even common in C++ (example: smart pointers), not something very special, it can be problematic to create bindings for it. And in case you want to replace automatically generated code with a custom one, in some cases it's easy, in some not. The positive aspect is that there is 'Qt for Python' community, where authors of Shiboken and PySide also participate, and they are friendly and help with all problems when they can.

  3. Debugging is not well supported in shiboken-based code yet. If something in the code is wrong, it can crash with a segmentation fault and the python debugger cannot catch the error. Generally it's not a big problem in this project, but if I write a lot of code, for example the whole module (widget) for UI and get such problem, then the only way is to debug step-by-step and find the problematic place.

Result and future work

As a result we got Python SDK for Matrix clients, using which developers can create working clients. There is also a working demo client. Advanced features need to be developed additionally, but as work on existing functionality showed it should be technically possible. Also, I plan to work on PyQuotient and Python client (similar to Quaternion) further, so I hope it's only the beginning of a story.

My personal conclusion

Creating C++ -> Python bindings was not new for me, I did similar earlier, but with other tools (SWIG) and code was without 3rd-party dependencies like Qt. I have experience with both Qt development and Python and I was convinced that part of an application with logic and definition of UI should be implemented in a high-level and simple way. To check this, during GSoC I learned a new tool (shiboken), pros&cons and aspects of using it, met new people (my mentor and people from Qt, Python, and Matrix communities), and got a new side project that I really like to work on. Also, it was a great opportunity to become an active member (developer) of the Matrix community, before I was only a user of Matrix clients.