Closed Lathreas closed 1 year ago
@Lathreas
fake_bpy_module's bpy_prop_collection contains no "new" function.
This is correct behavior.
https://docs.blender.org/api/current/bpy.types.bpy_prop_collection.html
bpy_prop_collection
does not contain new
function.
Instead, NodeLinks, BlendDataNodeTrees and etc have a new
function.
https://docs.blender.org/api/current/bpy.types.NodeLinks.html
https://docs.blender.org/api/current/bpy.types.BlendDataNodeTrees.html
BTW, why mypy does not check NodeLinks
and etc?
These class has a new
function.
Perhaps, do I mistake the usage of typing.Union
?
This is the same issue I reported here: https://github.com/nutti/fake-bpy-module/issues/30#issuecomment-1304367370 I'll move the convo to this issue.
@nutti
the base class of BlendDataMeshes is bpy_struct which has new method.
bpy_struct
doesn't have new
method, BlendDataMeshes
does.
Actually, this works well in VSCode with Pylance environment.
Looks like it's not working well for me or @Lathreas, is it working for you when you try to repro the code in my screenshots?
We will not fix this because we want to follow the official document not to increase the maintenance cost.
I hear you on this. I'll have a look at what the actual hierarchy is. Can you link to a patch you submit for the Blender docs before, as an example?
@xixixao
bpy_struct doesn't have new method, BlendDataMeshes does.
Sorry, I mistook the reference.
Yes, BlendDataMeshes has the new
method.
https://docs.blender.org/api/current/bpy.types.BlendDataMeshes.html
is it working for you when you try to repro the code in my screenshots?
Yes, it works on my environment. I will share the screenshot.
Can you link to a patch you submit for the Blender docs before, as an example?
https://docs.blender.org/api/current/bpy.types.BlendDataMeshes.html Above the link, you can see the class definition like;
class bpy.types.BlendDataMeshes(bpy_struct)
So the inheritance relationship is bpy_struct
(parent) <- BlendDataMeshes
(child).
@nutti I think you don't have type checking turned on. Try to change your VS Code settings:
You need to have at least basic
selected, and off
is the default (which only gives type completion). I think
@xixixao
Thanks. I can reproduce this error.
BTW, I'm not sure why typing.Union
is not worked in this context.
The official docs says bpy.data.meshes
is the combine of BlendDataMeshes
and bpy_prop_collection[Mesh]
.
Do you have an idea of this issue?
Thanks for the replies!
@nutti
BTW, why mypy does not check
NodeLinks
and etc? These class has anew
function. Perhaps, do I mistake the usage oftyping.Union
?BTW, I'm not sure why typing.Union is not worked in this context. The official docs says > bpy.data.meshes is the combine of BlendDataMeshes and bpy_prop_collection[Mesh]. Do you have an idea of this issue?
You are right that the problem is with typing.Union
and not with bpy_prop_collection
. You might have been thinking of the mathematical definition of a union acting on the members of the classes as if it were a set (https://en.wikipedia.org/wiki/Union_(set_theory)), but that definition is (confusingly) different from the programmatic definition of a union type (https://en.wikipedia.org/wiki/Union_type). typing.Union
instead means "this object can be any one of the entries, but not all at the same time". For example, typing.Any
is a typing.Union
of all possible types. A bit confusingly named, alas. But the behavior you are seeking is probably multiple inheritance, which combines the members of multiple classes.
Since an object with type typing.Union
can be either of the types, but not all at the same time, mypy checks all entries in the union separately and will check if any of them give an error message. This is because mypy cannot infer whether the object is, say, a NodeLinks
or a bpy_prop_collection[NodeLink]
at that particular point in time. For safety reasons, it will check both and produce an error if any of the entries of the Union has an error. The check for NodeLinks
doesn't give an error, since it contains a 'new'. But the check for bpy_prop_collection[NodeLink]
gives an error, causing the entire check to fail.
The correct behavior would have the object have access to the members of both NodeLinks
and bpy_prop_collection[NodeLink]
at the same time. Programmatically, this is accomplished through subclassing and multiple inheritance. For example, the following class would represent the combination of NodeLinks
and bpy_prop_collection[NodeLink]
that you are seeking:
class both_NodeLinks_and_PropCollection(NodeLinks, bpy_prop_collection[NodeLink])
Of course, this is not particularly elegant, because the class would just be empty boilerplate. But it would fix the issue. Looking at the Blender documentation, though, I am inclined to believe that the documentation itself could possibly be wrong.
A fix such as redefining NodeLinks
itself as
class bpy.types.NodeLinks(bpy_struct, bpy_prop_collection[NodeLink])
(and removing the typing.Union
stuff) would solve the issue as well, but that is indeed not what the Blender documentation says. That said, I have not encountered any type of collection type such as NodeLinks
without it being a combination with bpy_prop_collection
, so possibly changing the definition of such collection types to have multiple inheritance would be what Blender is doing internally.
It is important to note that both bpy_struct
and bpy_prop_collection[]
both aren't actually available in Blender --- they only exist in the Blender documentation according to the documentation itself. (see the note at https://docs.blender.org/api/current/bpy.types.bpy_prop_collection.html, for example. A similar note exists for bpy_struct). As such, it may very well be that NodeLinks
is indeed meant to be using multiple inheritance, but that the documentation is in error. But that should be investigated.
Either way, using inheritance will fix the issue, since a typing.Union
indeed works differently than what you intended in this context.
(Unrelatedly, thanks so much for this project by the way!)
Doing some more digging, it looks like the concept we are looking for is something like typing.Intersection
rather than typing.Union
. Alas, it is not accepted for inclusion into Python yet: https://github.com/python/typing/issues/213
So we'd have to use multiple inheritance instead for the time being.
We're going off of the documentation that simply is not correct / precise. I looked at the C source code and these collections are simply collections with additional methods.
So
class NodeLinks(bpy_struct, bpy_prop_collection[NodeLink]):
pass
is correct, and this is also correct:
class bpy_prop_collection(bpy_struct, typing.Generic[GenericType]):
pass
class NodeLinks(bpy_prop_collection[NodeLink]):
pass
We should adopt either of them here. We could also change the Blender docs, but I'm not sure the Blender docs support either of these inheritance declarations.
This issue is now fixed. Thanks for your suggestion to solve this issue, and sorry for a late response.
System Information
Expected behavior
Many Blender objects which are union of type
bpy_prop_collection[...]
have a 'new' function. For example:node_tree.outputs
is of type NodeTreeOutputs, and has a 'new' function.This should not give rise to an error in
mypy
when used correctly.Description about the bug
Mypy gives many false positives such as
despite correct usage of "new" - the fact that these are unions with
bpy_prop_collection
results in errors, since fake_bpy_module'sbpy_prop_collection
contains no "new" function.