Releases: SofaDefrost/Sofa.Component
Beta release of SofaPython3 code completion for SofaAward 2024
Improving SofaPython code completion
The contribution is about bringing code completion for SofaPython3 and increasing the user experience by providing code completion support for all the SOFA objects (eg: MechanicalObject, ... )
If you have 5 minutes, then you can go through this short video demonstrating a working code completion for Sofa.
If you have 45 minutes, then you can go through this long video explaining how code-completion works in general in python, what is wrong with our pybind11 binding called SofaPython3 and how we fix it.
Technical details
The contribution consists in several PRs for SofaPython3 as well as a separated python modules containing python helper code to get completion for all the SOFA.Component (including the ones in third party plugin).
On the contribution side, related issue and PR fixing them are:
- #417: General description of the problems: sofa-framework/SofaPython3#417
- #457: is fixing the "declaration order problem" of classes: sofa-framework/SofaPython3#457
- #461: is adding a way to implement custom typehint from pybind11 to sofa-framework/SofaPython3#461
These lays out a working basis for code completion working with current SOFA release. In addition to the aforementioned element,
the contribution is also composed of a method for code completion for dynamic attributes of SOFA objects (eg: data field). Demonstration of the method is in the Sofa.Component repository. In short, this completion is made possible by exposing the SOFA objects as importable python modules with python type-hints. These python modules being generated by a dedicated python script that extract the content of the SOFA factory in a similar way as the SOFA documentation system is working. This generation script can also be used to produce the python module for any SOFA objected as the ones provided by third party plugins.
Example
import Sofa.Core
from Sofa.Core import Node
from Sofa.Component.StateContainer.MechanicalObject import MechanicalObject
node = Node("Root")
d1 = node.addObject("MechanicalObject") # Old API , completion on methods, no completion of dynamic attributes eg: d1.position
d2 = cast(Mechanical, node.addObject("MechanicalObject")) # Old API, completion on methods and dynamic attributes but the use of cast is in-elegant.
d3 = node.addObject(MechanicalObject) # New API (experimental), completion on methods and dynamic attributes with elegant syntax
p = MechanicalObject.new_parameters() # New API (experimental), completion on methods and dynamic attribute before creation , for data field exploration
p.position = [1,2,3] # type-hints prevents writing p.position = "one"
d4 = node.addObject(MechanicalObject, *p)
Testing the beta
The contribution can be tested by downloading the latest version of the beta (at time of writing it is beta4) and unzip its content then copy the files in the Sofa python module (eg: on linux this module is in the directory SOFA_ROOT/lib/python3/site-packages/Sofa), (NB: some existing files will be overriden).
On a Linux system
SOFA_ROOT=/home/username/sofa/
PYTHONPATH=/home/username/sofa/lib/python3/site-packages
The unzipping should be extracted into
/home/username/sofa/lib/python3/site-packages/Sofa
So that, the files with extension .pyi are side by side the .py. with similar name.
After that, you should be able to get code completion with any modern editor as long as the environment variable PYTHONPATH is pointing to the valid directory.
Completion on Sofa.Core should work with existing SOFA version but advanced Sofa.Component requires the merge of the different PR.
Getting this work merged into master
Finally PR #468 sofa-framework/SofaPython3#468 and PR #453 sofa-framework/SofaPython3#453 despite not part of the contribution are WIP to integrate into the official packaging all the different aformentionned so that completition will be working out of the box in future SOFA release.