kyamagu / skia-python

Python binding to Skia Graphics Library
https://kyamagu.github.io/skia-python/
BSD 3-Clause "New" or "Revised" License
246 stars 43 forks source link

Generate type stubs #133

Open NextLight opened 3 years ago

NextLight commented 3 years ago

Is your feature request related to a problem? Please describe. Intellisense/autocomplete doesn't work in Visual Studio Code when using Pylance as the language server.
It works when using Jedi or the Microsoft language server but it still has issues understanding the return types of functions.

Describe the solution you'd like This is a known "issue" with Pylance, but they say it is a design choice. The solution should be to generate type stubs as discussed in this issue.
There is a discussion on how to automatically generate stubs for pybind11 here and the options seems to be either pybind11-stubgen or mypy's stubgen.

Describe alternatives you've considered I could use a different LS such as Jedi but it's worse in general and there would still be issues.

Additional context

kyamagu commented 3 years ago

Yes, this would be great

maliknajjar commented 2 years ago

Intellisense/autocomplete doesnt work for me as well when working with the skia-python package on vscode .. please fix this probleme

Nukiloco commented 2 years ago

It has been some what annoying so far having to look back and forth between the documentation/api and my code just to know what returns and what methods the skia package gives. Will there be a fix for this soon?

shuhei commented 2 years ago

I tried pybind11-stubgen and mypy's stubgen from the issue description. I'll share some findings here even though I haven't figured out a working solution for everyone.

pybind11-stubgen skia didn't generate stubs due to errors.

``` $ pip install pybind11-stubgen $ pybind11-stubgen skia [2022-03-13 17:12:47,680] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,680] {__init__.py:135} ERROR - def search(self: skia.BBoxHierarchy, query: skia.Rect, results: std::__1::vector >) -> None: ... [2022-03-13 17:12:47,680] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,713] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,713] {__init__.py:135} ERROR - def drawLine(self: skia.Canvas, x0: float, y0: float, x1: float, y1`: float, paint: skia.Paint) -> None: ... [2022-03-13 17:12:47,714] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,875] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,875] {__init__.py:135} ERROR - def queryYUVAInfo(self: skia.Codec, supportedDataTypes: SkYUVAPixmapInfo::SupportedDataTypes) -> object: ... [2022-03-13 17:12:47,875] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,903] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,903] {__init__.py:135} ERROR - def page(self: skia.Document, width: float, height: float) -> : ... [2022-03-13 17:12:47,903] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,946] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,946] {__init__.py:135} ERROR - def MakeMock(colorType: skia.GrColorType, compression: SkImage::CompressionType) -> skia.GrBackendFormat: ... [2022-03-13 17:12:47,946] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,947] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,947] {__init__.py:135} ERROR - def asMockCompressionType(self: skia.GrBackendFormat) -> SkImage::CompressionType: ... [2022-03-13 17:12:47,947] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,957] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,957] {__init__.py:135} ERROR - def compressedBackendFormat(self: skia.GrContext, compressionType: SkImage::CompressionType) -> skia.GrBackendFormat: ... [2022-03-13 17:12:47,957] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,958] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,958] {__init__.py:135} ERROR - def createCompressedBackendTexture(self: skia.GrContext, width: int, height: int, type: SkImage::CompressionType, color: skia.Color4f, mipMapped: skia.GrMipmapped, isProtected: skia.GrProtected = GrProtected.kNo) -> skia.GrBackendTexture: ... [2022-03-13 17:12:47,958] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,958] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,958] {__init__.py:135} ERROR - def createCompressedBackendTexture(self: skia.GrContext, width: int, height: int, type: SkImage::CompressionType, data: buffer, mipMapped: skia.GrMipmapped, isProtected: skia.GrProtected = GrProtected.kNo) -> skia.GrBackendTexture: ... [2022-03-13 17:12:47,958] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,967] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,967] {__init__.py:135} ERROR - def compressedBackendFormat(self: skia.GrContext_Base, arg0: SkImage::CompressionType) -> skia.GrBackendFormat: ... [2022-03-13 17:12:47,967] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,971] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,971] {__init__.py:135} ERROR - def __init__(self: skia.GrMockTextureInfo, colorType: skia.GrColorType, compressionType: SkImage::CompressionType, id: int) -> None: ... [2022-03-13 17:12:47,971] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:47,971] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:47,972] {__init__.py:135} ERROR - def compressionType(self: skia.GrMockTextureInfo) -> SkImage::CompressionType: ... [2022-03-13 17:12:47,972] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,001] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:48,001] {__init__.py:135} ERROR - def MakeFromNV12TexturesCopy(context: skia.GrContext, yuvColorSpace: skia.YUVColorSpace, nv12Textures: std::__1::vector >, imageOrigin: skia.GrSurfaceOrigin, imageColorSpace: skia.ColorSpace = None) -> skia.Image: ... [2022-03-13 17:12:48,001] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,001] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:48,002] {__init__.py:135} ERROR - def MakeFromNV12TexturesCopyWithExternalBackend(context: skia.GrContext, yuvColorSpace: skia.YUVColorSpace, nv12Textures: std::__1::vector >, imageOrigin: skia.GrSurfaceOrigin, backendTexture: skia.GrBackendTexture, imageColorSpace: skia.ColorSpace = None) -> skia.Image: ... [2022-03-13 17:12:48,002] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,009] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:48,009] {__init__.py:135} ERROR - def MakeFromYUVAPixmaps(context: skia.GrRecordingContext, yuvaPixmaps: skia.YUVColorSpace, yuvaTextures: std::__1::vector >, yuvaIndices: std::__1::vector >, imageSize: skia.ISize, imageOrigin: skia.GrSurfaceOrigin, buildMips: bool, limitToMaxTextureSize: bool = False, imageColorSpace: skia.ColorSpace = None) -> skia.Image: ... [2022-03-13 17:12:48,009] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,010] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:48,010] {__init__.py:135} ERROR - def MakeFromYUVATextures(context: skia.GrContext, yuvColorSpace: skia.YUVColorSpace, yuvaTextures: std::__1::vector >, yuvaIndices: std::__1::vector >, imageSize: skia.ISize, imageOrigin: skia.GrSurfaceOrigin, imageColorSpace: skia.ColorSpace = None) -> skia.Image: ... [2022-03-13 17:12:48,010] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,011] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:48,011] {__init__.py:135} ERROR - def MakeFromYUVATexturesCopy(context: skia.GrRecordingContext, yuvColorSpace: skia.YUVColorSpace, yuvaTextures: std::__1::vector >, yuvaIndices: std::__1::vector >, imageSize: skia.ISize, imageOrigin: skia.GrSurfaceOrigin, imageColorSpace: skia.ColorSpace = None) -> skia.Image: ... [2022-03-13 17:12:48,011] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,011] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:48,011] {__init__.py:135} ERROR - def MakeFromYUVATexturesCopyWithExternalBackend(context: skia.GrRecordingContext, yuvColorSpace: skia.YUVColorSpace, yuvaTextures: std::__1::vector >, yuvaIndices: std::__1::vector >, imageSize: skia.ISize, imageOrigin: skia.GrSurfaceOrigin, backendTexture: skia.GrBackendTexture, imageColorSpace: skia.ColorSpace = None) -> skia.Image: ... [2022-03-13 17:12:48,011] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,177] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:48,177] {__init__.py:135} ERROR - def Offset(points: std::__1::vector >, offset: skia.Point) -> std::__1::vector >: ... [2022-03-13 17:12:48,177] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,177] {__init__.py:131} ERROR - Generated stubs signature is degraded to `(*args, **kwargs) -> typing.Any` for [2022-03-13 17:12:48,177] {__init__.py:135} ERROR - def Offset(points: std::__1::vector >, dx: float, dy: float) -> std::__1::vector >: ... [2022-03-13 17:12:48,177] {__init__.py:136} ERROR - ^-- Invalid syntax [2022-03-13 17:12:48,321] {__init__.py:957} INFO - Useful link: Avoiding C++ types in docstrings: [2022-03-13 17:12:48,321] {__init__.py:958} INFO - https://pybind11.readthedocs.io/en/latest/advanced/misc.html#avoiding-cpp-types-in-docstrings ```

stubgen looks more promising (https://github.com/sizmailov/pybind11-stubgen/issues/31). I was able to generate type stubs that work more or less. I ran the following in my project root directory:

pip install mypy skia
stubgen -p skia -o . # Generates stubs in `./skia`
touch skia/py.typed # https://peps.python.org/pep-0561/
sed -i '' 's/Sk//g' skia/__init__.pyi # Removes the Sk prefix

The generated skia directory contains type stubs for skia. It could be put anywhere in sys.path like your project root or site-packages.

Now I got type stubs that are somewhat useful for autocompletion and basic type check, but they still have many issues:

I hope this helps for someone who's willing to investigate it further.