Embarcadero / DelphiVCL4Python

Delphi's VCL library as a Python module for building Windows GUI
Other
245 stars 54 forks source link

Development of Stubs with Delphi Documentation #87

Open excript opened 5 months ago

excript commented 5 months ago

I used the delphivcl library in the development of a commercial application and tired of searching in the Delphi documentation for the signature of class members, I started building the stub file containing the complete signature of the internal class members, as well as their documentation.

I know that stubs for delphivcl and delphifmx are under development, and my goal here is to contribute to the current work. The official stubs provided with the delphivcl and delphifmx packages do not contain the complete list of functions and methods, and most importantly, they have not yet extracted all the existing documentation in Delphi.

To facilitate the review of the stub I developed with the official stub, I organized the definition of the classes following the order of the official stub.

I also started merging specific class members from the Python packages, that is, the properties, methods, and built-in functions of the delphivcl and delphifmx modules.

An example of the merge I made can be seen below, a set of specific Python symbols.

    __hash__: ClassVar[None] = ...

    def __contains__(self, other) -> bool:
    def __delattr__(self, name) -> Any:
    def __eq__(self, other) -> bool:
    def __ge__(self, other) -> bool:
    def __getitem__(self, index) -> Any:
    def __gt__(self, other) -> bool:
    def __iter__(self) -> Any:
    def __le__(self, other) -> bool:
    def __len__(self) -> int:
    def __lt__(self, other) -> bool:
    def __ne__(self, other) -> bool:
    def __setattr__(self, name, value) -> Any:

I am currently sharing only the delphivcl stub because, as mentioned earlier, it is necessary to merge specific Python class members and make numerous other adjustments.

EXISTING ISSUES

Type Hint

I converted the Delphi documentation to Python class stubs while developing a commercial application. At that time, I had not yet studied the typing library, and due to deadlines in delivering the work, I gradually developed it without using the correct type hints notation.

The initial goal was to speed up the discovery of the notation of the internal members of the classes, especially since I constantly needed to use Delphi's Code Complete to be able to write Python code.

Unlike the official stub where the event method declaration is written using mainly type hints, I developed the stub with the intention of preserving the entire notation of the function and method signatures, including preserving the parameter names and their type names.

The stub I developed can be considered the full text of the official documentation, even preserving tables, links, and examples in Delphi and C++.

The only change in the text of the official documentation was the removal of the T prefix from the class names. I tried to use the official naming of the delphivcl and delphifmx libraries.

As an example, below you can see the difference between the official stub and the stub I developed. The first code snippet is the declaration of the OnMouseDown method contained in the official stub, and following it is the declaration of the same method in my stub.

    # Official stub

    OnMouseDown: Callable[[Object,MouseButton,ShiftState,int,int],None]
    """Callable[[Object, MouseButton, ShiftState, int, int], None]:"""
    # Stub I developed

    def OnMouseDown(self, Sender: Object, Button: MouseButton, Shift: ShiftState, X: int, Y: int) -> None:
        '''
        # OnMouseDown: MouseEvent
        Occurs when the user presses a mouse button with the mouse pointer over a control.

        Use the `OnMouseDown <Vcl.Controls.Control.OnMouseDown.htm>`__ event handler to implement any special processing that should occur as a result of pressing a mouse button.

        The `OnMouseDown <Vcl.Controls.Control.OnMouseDown.htm>`__ event handler can respond to *left*, *right*, or *center* mouse button presses and *Shift* key plus mouse-button combinations. *Shift* keys are the *Shift*, *Ctrl*, and *Alt* keys. ``'X'`` and ``'Y'`` are the pixel coordinates of the mouse pointer in the client area of the ``Sender``.

        `OnMouseDown <Vcl.Controls.Control.OnMouseDown.htm>`__ is an event handler of type `Vcl.Controls.MouseEvent <Vcl.Controls.MouseEvent.htm>`__.
        '''

CLASS METHODS

My stub has not yet defined the @classmethod decorator existing in the official stub.

PRINCIPLE USED IN STUB CONSTRUCTION

The delphivcl 1.0.5 contains 140 classes, the official stub, contained in the delphivcl package, has 138 class notations defined, while my stub has 287 declared classes!

A significant portion of the 287 defined class definitions does not contain any notations in the internal members; the goal was to provide the definition and documentation of classes used, for example, in property types or in the type of parameters of a function or method.

As initially stated, the goal when building the stub was to provide notations and documentation from the Python code editor. No standards or techniques for writing stub files were used in development. Even so, the result obtained from the PyCharm IDE was excellent; the editor flags issues when trying to invoke methods and functions with different numbers of parameters or values than those defined in the stub.

Below is a screenshot of how PyCharm displays the method signature, as well as its documentation when hovering over a particular function.

Therefore, declaring so many classes in the stub file is the way to provide, in addition to the classes and their members contained in the packages.

PyCharm finds approximately 1000 errors in the declarations of the official stub, in defining the types used in the definitions of the internal members of the classes.

There is another reason why I chose to define all these classes: to prevent the interpreter from reporting hundreds of errors when it cannot find the types of the class members, preventing us from locating other types of problems, such as syntax errors.

The images below show the errors reported by PyCharm for the official stub.

34V24kW4mn

pycharm64_xByMSUttI5

It is important to say that issues reported by PyCharm do not interfere with the proper functioning of the stub! Code Complete, for example, works perfectly, returning the names of the internal members of the classes, as well as their signatures.

Even though there is no problem with the operation of the stub, the truth is that such errors are reported because there are missing class definitions, which are often the types of the members in the signature of properties, functions, or methods. Therefore, there is a reason to define such classes within the stub.

Previously, the method OnMouseDown was used as an example. The method signature has 2 typed parameters: MouseButton, ShiftState.

In both types, we basically find the valid options that the parameter supports. When such types are not defined in the stub, it becomes necessary to search the official documentation or to discover the options through debugging.

Below is the definition of the MouseButton class, as well as its 3 members.

Even without using the type notation correctly, the mere existence of the existing members within the classes is already enough to understand and know the allowed options and infer their functioning.

    class MouseButton:
        mbLeft: ...
        mbRight: ...
        mbMiddle: ...

    OnMouseDown: Callable[[Object,MouseButton,ShiftState,int,int],None]
    def OnMouseDown(self, Sender: Object, Button: MouseButton, Shift: ShiftState, X: int, Y: int) -> None:

Finally, that is the reason why there are 287 classes in the stub file I developed, even though there are only 140 classes contained in the delphivcl package.

TRANSLATION

Two years ago, I started translating the documentation of delphivcl and delphifmx into Portuguese. I found out that stub files can also be used in separating source code from documentation.

Being a stub file somewhat like a C++ header file, the Python packages used in the module and package documentation cycle (docutils, sphinx, and gettext) can be utilized, and I used them in generating the POT files.

Over the past years, I specialized in the continuous software and documentation translation cycle (internationalization), having translated several books and the documentation of more than 10 Python packages, including the complete Python documentation.

In addition to knowledge and experience with the continuous translation cycle, I developed specialized tools over time for translating technical text, and of course, I gradually trained an AI with the terminologies and jargon found in software development and programming literature in general.

It's important to mention that the use of machine translation, no matter how trained the AI may be, is only meant to speed up the work, but a sentence is marked as finished only after manual review and correction.

As can be seen in the image below, the English sentences were submitted on 10/22/2022, and the last time there were translated or marked as finished sentences was on 03/04/2024.

delphifmx-status

At this moment, the delphifmx library has 75% of its sentences verified, and delphivcl is 70% translated.

In other words, the documentation of delphifmx has 10,159 sentences, practically all sentences have a translation, and 7,731 have already been verified and corrected (manually), leaving only 2,428 sentences for completion.

Screenshots of the current state of translation, the platform used for management is Transifex.

delphivcl transifex-delphivcl

delphifmx transifex-delphifmx

lmbelo commented 5 months ago

Hello,

delphivcl and delphifmx already have stubs. Further enhancements or modifications should follow the standards.

We need to generate stubs programmatically to facilitate development. How does your tool work?

In advance, thank you very much for your help and interest.