skia-python icon indicating copy to clipboard operation
skia-python copied to clipboard

Generate type stubs

Open NextLight opened this issue 4 years ago • 4 comments

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

NextLight avatar Dec 03 '20 11:12 NextLight

Yes, this would be great

kyamagu avatar Jan 05 '21 03:01 kyamagu

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

maliknajjar avatar Jan 29 '22 21:01 maliknajjar

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?

Nukiloco avatar Feb 25 '22 00:02 Nukiloco

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<int, std::__1::allocator<int> >) -> 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<GrBackendTexture, std::__1::allocator<GrBackendTexture> >, 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<GrBackendTexture, std::__1::allocator<GrBackendTexture> >, 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<SkPixmap, std::__1::allocator<SkPixmap> >, yuvaIndices: std::__1::vector<SkYUVAIndex, std::__1::allocator<SkYUVAIndex> >, 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<GrBackendTexture, std::__1::allocator<GrBackendTexture> >, yuvaIndices: std::__1::vector<SkYUVAIndex, std::__1::allocator<SkYUVAIndex> >, 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<GrBackendTexture, std::__1::allocator<GrBackendTexture> >, yuvaIndices: std::__1::vector<SkYUVAIndex, std::__1::allocator<SkYUVAIndex> >, 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<GrBackendTexture, std::__1::allocator<GrBackendTexture> >, yuvaIndices: std::__1::vector<SkYUVAIndex, std::__1::allocator<SkYUVAIndex> >, 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<SkPoint, std::__1::allocator<SkPoint> >, offset: skia.Point) -> std::__1::vector<SkPoint, std::__1::allocator<SkPoint> >: ...
[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<SkPoint, std::__1::allocator<SkPoint> >, dx: float, dy: float) -> std::__1::vector<SkPoint, std::__1::allocator<SkPoint> >: ...
[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:

  • a field called def: I just commented it out...
  • Static methods are generated as instance methods: I manually added @staticmethod and removed the first argument of the ones that I use, but this is not a scalable solution.
  • Many many Any

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

shuhei avatar Mar 13 '22 16:03 shuhei