electronstudio / raylib-python-cffi

Python CFFI bindings for Raylib
http://electronstudio.github.io/raylib-python-cffi
Eclipse Public License 2.0
142 stars 29 forks source link

Added pyray stub #39

Closed Guilherme32 closed 2 years ago

Guilherme32 commented 2 years ago

Adding a pyray stub so that IDEs can use autocompletion and not show unresolved references on the code

electronstudio commented 2 years ago

How did you generate this? I’m reluctant to put anything in that can’t be auto generated because I won’t have time to update it manually on each new release.

Guilherme32 commented 2 years ago

So... I kinda did it mannualy. I don't know how it could be done on build time, but this is how I did it. I first imported this handy function from the inspect library:

from inspect import signature

Then I added some prints to the part of the pyray.py script that adds the attributes, in order to build the text for the stub:

for name, attr in getmembers(rl):
    # print(name, attr)
    uname = inflection.underscore(name).replace('3_d', '_3d').replace('2_d', '_2d')
    if isbuiltin(attr) or str(type(attr)) == "<class '_cffi_backend.__FFIFunctionWrapper'>":
        # print(attr.__call__)
        # print(attr.__doc__)
        # print(attr.__text_signature__)
        # print(dir(attr))
        # print(dir(attr.__repr__))
        f = makefunc(attr)
        setattr(PyRay, uname, f)

        sig = signature(f)
        return_type = str(attr).split(' ')[1][1:]           # this isolates the type

        if return_type == 'unsigned':
         return_type = str(attr).split(' ')[2]

        if return_type == 'void':
            return_type = 'None'

        print(f"def {uname}{sig} -> {return_type}: ...")

        # def wrap(*args):
        #    print("call to ",attr)
        # setattr(PyRay, uname, lambda *args: print("call to ",attr))
    else:
        print(f"{name}: {str(type(attr))[8:-2]}")           # this isolates the type
        setattr(PyRay, name, attr)

for struct in ('Vector2', 'Vector3', 'Vector4', 'Camera2D', 'Camera3D', 'Quaternion', 'Color', 'Rectangle'):
    f = makeStructHelper(struct)
    print(f"{struct}: struct")
    setattr(PyRay, struct, f)

After importing pyray, I copied the entire block from my command line and pasted onto the newly created stub, under the RayPy class, using mass indent to put it all in the proper scope. I then commented these lines for it to not print again. I imagine it wouldn't be so hard to save these lines to a file instead of printing, but I don't know how to do it automatically on github...

electronstudio commented 2 years ago

apparently the stub can be a separate .pyi file, so i'm going to do that, unless any objections?

would also be nice if i could make the hints more useful listing arguments

electronstudio commented 2 years ago

i have figured out how to list argument types, but not names.

Guilherme32 commented 2 years ago

I made some modifications. I made a script that builds it. I feel like there might be a more automated way of doing it, but I couldn't find it. It now includes a more descriptive arguments list and the cffi generated docstring, so it can be seen the C function signature. I will upload it and the build pyi and start a new request.

electronstudio commented 2 years ago

I already made an automated build script! Haven't commited it because want to test it a bit more.

electronstudio commented 2 years ago

would be interested to see yours though, it might be better

Guilherme32 commented 2 years ago

Oh, I really think yours will be better, but I put it with the new pull request, if you wish to take a look

electronstudio commented 2 years ago

well here is what i have so far, now committed in master https://github.com/electronstudio/raylib-python-cffi/commit/3044797382a7e47a6534c74c3e079cd3752de446

electronstudio commented 2 years ago

to generate:

python3 create_stub.py > raylib/pyray.pyi
Guilherme32 commented 2 years ago

Cool! I think including the doc can be useful exactly because struct returns all appear to be the same. With the doc you can look at the original C signature and see the real expected return type. Also, I created an inner class called struct so PyCharm recognizes it and shows at least the word on the return type. It is on the generator comitted to the pull request, if you wish to take a look

Guilherme32 commented 2 years ago

I didn't know you could save the script's output with '>', so I made it so the script creates the file and edits it

electronstudio commented 2 years ago

Yeah you can do a lot of cool stuff with shell scripting, often easier than writing a program.

I tried adding docstrings myself but I couldn't see them anywhere PyCharm. Do they appear somewhere in PyCharm for you?

Guilherme32 commented 2 years ago

They appear right below the function signature when hovering or when selecting the function on the autocomplete dropdown thing

electronstudio commented 2 years ago

Weird, I don't get them on the autocomplete but I do on the hover.