Closed yck011522 closed 3 years ago
I've posted an issue on Pylance's Github about it. You can check it here, but that is the summary: If you want your package to work correctly with static type checkers, you should either avoid using wildcard imports or replace dynamic all expressions with static expressions like all = ['cat', 'dog'].
Arh, that's an interesting reply from them. Perhaps it is modifiable from compas's side.
Pylance is based on Pyright, which is a static type analyzer. It is able to evaluate expressions like __all__
= ['cow'], but it cannot evaluate something as dynamic as __all__
= [name for name in dir() if not name.startswith('``')]._
This of course will increase the maintenance work on compas development. I personally like the goal of this two-level import in compas where I believe is to shield users from internal implementation changes from version to version, I just don't know how much more extra maintenance work there is to be done.
do you know if it can work with *.pyi
files to detect the contents of packages and modules?
I do not know.
do you know if it can work with *.pyi files to detect the contents of packages and modules?
I think that would work. We would need to auto-generate them otherwise the effort to keep them up-to-date would be too high.
what seems to yield the correct result is to add a __init__.pyi
at every second level package. so for example compas.datastructures.__init__.pyi
. this is more or less what numpy
does (all of there __all__
variables are also dynamically generated), albeit at the import levels that make sense for them.
Pylance correctly autocompletes if i add this to compas.datastructures.__init__.pyi
from .mesh import BaseMesh
from typing import Any
class Mesh(BaseMesh):
bounding_box: Any = ...
bounding_box_xy: Any = ...
collapse_edge: Any = ...
connected_components: Any = ...
cut: Any = ...
dual: Any = ...
face_adjacency: Any = ...
flip_cycles: Any = ...
is_connected: Any = ...
smooth_centroid: Any = ...
smooth_area: Any = ...
split_edge: Any = ...
split_face: Any = ...
transform: Any = ...
transformed: Any = ...
unify_cycles: Any = ...
quads_to_triangles: Any = ...
def transform_numpy(self, M: Any) -> None: ...
def to_trimesh(self) -> None: ...
def to_quadmesh(self) -> None: ...
however, it seems a bit complicated to automate. stubgen
generates stubs per package / module and not at the level they have been dynamically pulled up to.
perhaps one could automate collecting the stubs based on the contents of __all__
at the second level but that is a bit tedious and error-prone...
a simpler definition also works
from .mesh import *
class Mesh(BaseMesh):
pass
however, the following doesn't
from .mesh import *
the numpy
stuff i was talking about
https://github.com/numpy/numpy/blob/master/numpy/__init__.pyi
gentle ping.
working on it. will send a pr by the end of next week...
Thanks so much. This will be major life saver. 🌈
solved since version 1.2.0
@brgcode and all who worked on this. Just wanted to say thank you. Worked perfectly with VScode and pylance now. 👍
Feature Request
Pylance is a feature rich python language plugin for VSCode. It provide code analysis and intellisense.
The intellisense function works with python default functions and types and almost all other libraries I used (such as numpy). However it does not work with compas.
I suspect this is caused by the 2-layer-deep import routing that compas uses. If I write the full path, or in fact keep the default full path that Pylance automatically creates, the intellisense works, See below where
intersection_line_plane
is yellow, that one works.I think @Achillx has faced similar problem.