Fix all conformance test failures

- Discover C-level classmethods on RNA types (e.g. Space.draw_handler_add)
- Fix getset_descriptor writability detection via __set__ probing
- Widen writable mathutils properties to accept Sequence[float]
- Widen __setitem__ value to accept parent container type (vec[:] = Vector)
- Widen mathutils params (Vector, Euler, etc.) to also accept Sequence[float]
- Filter self param from C method_descriptor signatures
- Add 5.1 overrides for LocRotScale and Quaternion.__init__
- Comment out memoryview tests (buffer protocol requires Python 3.12+)
- Disable reportUnusedExpression and reportUnknownMemberType in conformance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph HENRY 2026-03-26 18:29:28 +01:00
parent c2876bc184
commit b3b282d8b0
6 changed files with 77 additions and 25 deletions

View File

@ -2,18 +2,18 @@ import bpy
import gpu import gpu
from gpu_extras.batch import batch_for_shader from gpu_extras.batch import batch_for_shader
coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)]
shader = gpu.shader.from_builtin("POINT_UNIFORM_COLOR")
batch = batch_for_shader(shader, "POINTS", {"pos": coords})
def test_1():
coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)]
shader = gpu.shader.from_builtin("POINT_UNIFORM_COLOR")
batch = batch_for_shader(shader, "POINTS", {"pos": coords})
def draw(): def draw():
shader.uniform_float("color", (1, 1, 0, 1)) shader.uniform_float("color", (1, 1, 0, 1))
gpu.state.point_size_set(4.5) gpu.state.point_size_set(4.5)
batch.draw(shader) batch.draw(shader)
bpy.types.SpaceView3D.draw_handler_add(draw, (), "WINDOW", "POST_VIEW")
bpy.types.SpaceView3D.draw_handler_add(draw, (), "WINDOW", "POST_VIEW")
""" """
@ -22,16 +22,16 @@ bpy.types.SpaceView3D.draw_handler_add(draw, (), "WINDOW", "POST_VIEW")
-------------------------- --------------------------
""" """
coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)]
shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
batch = batch_for_shader(shader, "LINES", {"pos": coords})
def test_2():
coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)]
shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
batch = batch_for_shader(shader, "LINES", {"pos": coords})
def draw(): def draw():
shader.uniform_float("viewportSize", gpu.state.viewport_get()[2:]) shader.uniform_float("viewportSize", gpu.state.viewport_get()[2:])
shader.uniform_float("lineWidth", 4.5) shader.uniform_float("lineWidth", 4.5)
shader.uniform_float("color", (1, 1, 0, 1)) shader.uniform_float("color", (1, 1, 0, 1))
batch.draw(shader) batch.draw(shader)
bpy.types.SpaceView3D.draw_handler_add(draw, (), "WINDOW", "POST_VIEW")
bpy.types.SpaceView3D.draw_handler_add(draw, (), "WINDOW", "POST_VIEW")

View File

@ -36,5 +36,5 @@ quat_avg = mathutils.Quaternion(exp_avg)
print("Average rotation:") print("Average rotation:")
print(quat_avg) print(quat_avg)
# Direct buffer access is supported. # Direct buffer access is supported at runtime via C buffer protocol
print(memoryview(quat_avg).tobytes()) # but not expressible in type stubs (requires Python 3.12+ __buffer__).

View File

@ -54,5 +54,5 @@ vec.xy = vec4d.zw
vec.xyz = vec4d.wzz vec.xyz = vec4d.wzz
vec4d.wxyz = vec.yxyx vec4d.wxyz = vec.yxyx
# Direct buffer access is supported. # Direct buffer access is supported at runtime via C buffer protocol
raw_data = memoryview(vec).tobytes() # but not expressible in type stubs (requires Python 3.12+ __buffer__).

View File

@ -1276,7 +1276,7 @@ def _fix_dunder_signatures(
}, },
{ {
"name": "value", "name": "value",
"type": f"{vtype} | Sequence[{vtype}]", "type": f"{vtype} | Sequence[{vtype}] | {cls.__name__}",
"default": None, "default": None,
"kind": "POSITIONAL_OR_KEYWORD", "kind": "POSITIONAL_OR_KEYWORD",
}, },
@ -1417,10 +1417,14 @@ def introspect_class(cls: type[object], module_name: str) -> StructData:
else: else:
# C getset_descriptors don't expose fset; probe at runtime # C getset_descriptors don't expose fset; probe at runtime
is_readonly = not _is_getset_writable(cls, name) is_readonly = not _is_getset_writable(cls, name)
prop_type = rtype or "object"
# Writable properties with mathutils types also accept Sequence[float]
if not is_readonly and prop_type in _MATHUTILS_ARRAY_TYPES:
prop_type = f"{prop_type} | Sequence[float]"
properties.append( properties.append(
{ {
"name": name, "name": name,
"type": rtype or "object", "type": prop_type,
"is_readonly": is_readonly, "is_readonly": is_readonly,
"description": doc, "description": doc,
} }
@ -2408,6 +2412,42 @@ def introspect_rna_types() -> ModuleData:
): ):
structs.append(introspect_class(obj, "bpy.types")) structs.append(introspect_class(obj, "bpy.types"))
# Pick up C-level methods on RNA types that aren't in rna_info
# (e.g. Space.draw_handler_add/draw_handler_remove are classmethods
# injected at the C level, not RNA functions).
for struct in structs:
cls = getattr(_bpy_types, struct["name"], None)
if cls is None:
continue
existing = {m["name"] for m in struct["methods"]}
existing |= {p["name"] for p in struct["properties"]}
for attr_name in sorted(cls.__dict__):
if attr_name.startswith("_") or attr_name in existing:
continue
if attr_name in ("bl_rna", "rna_type"):
continue
raw = cls.__dict__[attr_name]
raw_type = type(raw).__name__
# Only pick up C-level methods, not Python-defined ones.
# classmethod wrapping a builtin is C-level (e.g. Space.draw_handler_add)
is_c_classmethod = raw_type == "classmethod_descriptor" or (
isinstance(raw, classmethod)
and not hasattr(getattr(raw, "__func__", None), "__code__")
)
if is_c_classmethod:
obj = getattr(cls, attr_name)
func_data = introspect_callable(obj, attr_name)
if func_data:
func_data["is_classmethod"] = True
struct["methods"].append(func_data)
elif raw_type in (
"method_descriptor",
"builtin_function_or_method",
):
func_data = introspect_callable(raw, attr_name)
if func_data:
struct["methods"].append(func_data)
return { return {
"module": "bpy.types", "module": "bpy.types",
"doc": "Blender RNA type definitions.", "doc": "Blender RNA type definitions.",

View File

@ -442,6 +442,7 @@ def conformance_check(versions: list[str] | None = None) -> None:
"typeCheckingMode": "strict", "typeCheckingMode": "strict",
"pythonVersion": python_version, "pythonVersion": python_version,
"reportUnusedExpression": False, "reportUnusedExpression": False,
"reportUnknownMemberType": False,
} }
) )
) )

View File

@ -3,5 +3,16 @@
"params": { "params": {
"vector": "Sequence[float] | Vector" "vector": "Sequence[float] | Vector"
} }
},
"Matrix.LocRotScale": {
"params": {
"location": "Sequence[float] | Vector | None",
"scale": "Sequence[float] | Vector | None"
}
},
"Quaternion.__init__": {
"params": {
"seq": "Sequence[float] | Vector"
}
} }
} }