How to generate .pyi files for a compiled Python extension?
Question:
I build a compiled Python extension (.pyd
file) with C++ and pybind11
. I would like to generate a single Python interface .pyi
file for my .pyd
file.
There are a few similar questions referring to the mypy
stubgen
module, however, this one produces a UnicodeError
trying to run stubgen Dummy
where Dummy
is Dummy.pyd
file:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x90 in position 2: invalid start byte
Another project, make-stub-files does not work with .pyd
files at all, giving the ('not a python file'
error.
Are there any tools that could let me generate .pyi files either from the source .cpp
files or from compiled .pyd
files?
The issue is registered in the mypy
GitHub repository.
Answers:
The issue was registered in the mypy
GitHub source repository and fixed in a pull request.
The reason for the issue was that when mypy
was trying to figure out whether a given module is a Python extension it checked for the .so
file extension used on Linux, but did not check for the .pyd
file extension used on Windows.
Unfortunately, mypy
‘s stubgen
does not (yet) include docstrings and signatures. However, it is relatively easy to automatically generate your own stub’s using the Python native inspect
package. For example, I use something along the lines of:
import my_package
import inspect
with open('my_package.pyi', 'w') as f:
for name, obj in inspect.getmembers(nf):
if inspect.isclass(obj):
f.write('n')
f.write(f'class {name}:n')
for func_name, func in inspect.getmembers(obj):
if not func_name.startswith('__'):
try:
f.write(f' def {func_name} {inspect.signature(func)}:n')
except:
f.write(f' def {func_name} (self, *args, **kwargs):n')
f.write(f" '''{func.__doc__}'''")
f.write('n ...n')
So essentially, first install your package and afterwards you can run this script to create a .pyi
. You can change it easily to your liking! Note that you must correctly define docstrings in your C/C++ code: https://stackoverflow.com/a/41245451/4576519
I build a compiled Python extension (.pyd
file) with C++ and pybind11
. I would like to generate a single Python interface .pyi
file for my .pyd
file.
There are a few similar questions referring to the mypy
stubgen
module, however, this one produces a UnicodeError
trying to run stubgen Dummy
where Dummy
is Dummy.pyd
file:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x90 in position 2: invalid start byte
Another project, make-stub-files does not work with .pyd
files at all, giving the ('not a python file'
error.
Are there any tools that could let me generate .pyi files either from the source .cpp
files or from compiled .pyd
files?
The issue is registered in the mypy
GitHub repository.
The issue was registered in the mypy
GitHub source repository and fixed in a pull request.
The reason for the issue was that when mypy
was trying to figure out whether a given module is a Python extension it checked for the .so
file extension used on Linux, but did not check for the .pyd
file extension used on Windows.
Unfortunately, mypy
‘s stubgen
does not (yet) include docstrings and signatures. However, it is relatively easy to automatically generate your own stub’s using the Python native inspect
package. For example, I use something along the lines of:
import my_package
import inspect
with open('my_package.pyi', 'w') as f:
for name, obj in inspect.getmembers(nf):
if inspect.isclass(obj):
f.write('n')
f.write(f'class {name}:n')
for func_name, func in inspect.getmembers(obj):
if not func_name.startswith('__'):
try:
f.write(f' def {func_name} {inspect.signature(func)}:n')
except:
f.write(f' def {func_name} (self, *args, **kwargs):n')
f.write(f" '''{func.__doc__}'''")
f.write('n ...n')
So essentially, first install your package and afterwards you can run this script to create a .pyi
. You can change it easily to your liking! Note that you must correctly define docstrings in your C/C++ code: https://stackoverflow.com/a/41245451/4576519