nutti / fake-bpy-module

Fake Blender Python API module collection for the code completion.
MIT License
1.35k stars 96 forks source link

Missing "magic" dunder methods #97

Closed MicaelJarniac closed 2 years ago

MicaelJarniac commented 2 years ago

System Information

Expected behavior
The following should work:

def test(bpc: bpy.types.bpy_prop_collection) -> None:
    foo = bpc[-1]

If I inspect bpy.types.bpy_prop_collection inside of Blender, it has the following:

>>> dir(bpy.types.bpy_prop_collection)
['__bool__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'as_bytes', 'data', 'find', 'foreach_get', 'foreach_set', 'get', 'id_data', 'items', 'keys', 'path_from_id', 'rna_type', 'update', 'values']

So inside Blender, it does have a __getitem__ method, with the following:

>>> help(bpy.types.bpy_prop_collection.__getitem__)
Help on wrapper_descriptor:

__getitem__(self, key, /)
    Return self[key].

Description about the bug

def test(bpc: bpy.types.bpy_prop_collection) -> None:
    foo = bpc[-1]  # Value of type "bpy_prop_collection" is not indexable - mypy(error)

Inside of the fake bpy module, bpy.types.bpy_prop_collection has only the following:

>>> dir(bpy.types.bpy_prop_collection)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'find', 'foreach_get', 'foreach_set', 'get', 'items', 'keys', 'values']

Notice it has no __getitem__:

>>> help(bpy.types.bpy_prop_collection.__getitem__)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'bpy_prop_collection' has no attribute '__getitem__'. Did you mean: '__setattr__'?

And if I inspect its source, I can't find any "magic" dunder methods.

Additional comments
It seems like there are absolutely no dunder methods throughout the entire fake bpy module.

MicaelJarniac commented 2 years ago

I believe this issue to be related: https://github.com/nutti/fake-bpy-module/issues/76

MicaelJarniac commented 2 years ago

It might be even better to do it with Generic, like so:

from typing import TypeVar, Generic, Union

T = TypeVar("T")

class bpy_prop_collection(Generic[T]):
    def __getitem__(self, key: Union[str, int]) -> T:
        pass

class Screen(ID, bpy_struct):
    areas: bpy_prop_collection[Area] = None
nutti commented 2 years ago

Good catch. I think we should change the analysis algorithm to support this.

nutti commented 2 years ago

I applied @MicaelJarniac 's suggestion now. I think this patch improves the code completion.