diff --git a/generate_stubs.py b/generate_stubs.py index ae8277f..ac19c5d 100644 --- a/generate_stubs.py +++ b/generate_stubs.py @@ -553,6 +553,8 @@ def generate_types_stub( typing_imports = ["Generic", "TypeVar"] if "Literal[" in all_type_strs: typing_imports.append("Literal") + if re.search(r"\bSelf\b", all_type_strs): + typing_imports.append("Self") abc_imports = ["Iterator"] if "Callable" in all_type_strs: diff --git a/introspect.py b/introspect.py index ec9e81a..aa9615e 100644 --- a/introspect.py +++ b/introspect.py @@ -542,9 +542,7 @@ _UNDEFINED_TYPE_NAMES = { "_PropertyDeferred", } -_UNDEFINED_TYPE_MAP = { - "ContextTempOverride": "object", -} +_UNDEFINED_TYPE_MAP: dict[str, str] = {} _UNDEFINED_GENERIC_TYPES = {"BMVertSkin"} @@ -1226,6 +1224,8 @@ _USEFUL_DUNDERS = { "__le__", "__gt__", "__ge__", + "__enter__", + "__exit__", } @@ -1293,6 +1293,7 @@ def _fix_dunder_signatures( "__ge__": "bool", "__delitem__": "None", "__setitem__": "None", + "__exit__": "None", } for method in methods: fixed = _FIXED_RETURNS.get(method["name"]) @@ -1300,6 +1301,15 @@ def _fix_dunder_signatures( method["return_type"] = fixed if method["name"] == "__len__": method["params"] = [] + if method["name"] == "__enter__": + method["return_type"] = "Self" + method["params"] = [] + if method["name"] == "__exit__": + method["params"] = [ + {"name": "exc_type", "type": "type[BaseException] | None", "default": None, "kind": "POSITIONAL_OR_KEYWORD"}, + {"name": "exc_val", "type": "BaseException | None", "default": None, "kind": "POSITIONAL_OR_KEYWORD"}, + {"name": "exc_tb", "type": "object", "default": None, "kind": "POSITIONAL_OR_KEYWORD"}, + ] if method["name"] == "__delitem__": method["params"] = [ { @@ -2680,6 +2690,31 @@ def introspect_rna_types() -> ModuleData: _merge_non_rna_bpy_types(structs, _bpy_types) _merge_missing_c_methods(structs, _bpy_types) + # Discover hidden C types reachable only via method return values + # (e.g. ContextTempOverride from Context.temp_override()). + known = {s["name"] for s in structs} + bpy = importlib.import_module("bpy") + ctx = getattr(bpy, "context") + _HIDDEN_TYPE_PROBES: list[tuple[object, str]] = [ + (ctx, "temp_override"), + ] + for obj, method_name in _HIDDEN_TYPE_PROBES: + func = getattr(obj, method_name, None) + if func is None or not callable(func): + continue + try: + result = func() + result_cls = result.__class__ + if result_cls.__name__ not in known: + structs.append(introspect_class(result_cls, "bpy.types")) + known.add(result_cls.__name__) + # Clean up context manager if applicable + exit_fn = getattr(result, "__exit__", None) + if exit_fn is not None: + exit_fn(None, None, None) + except Exception: + pass + return { "module": "bpy.types", "doc": "Blender RNA type definitions.",