Fix all typecheck errors in source code
- Fix partially unknown types from empty set() literals with annotations - Use getattr-based indexing for runtime probes on object-typed instances - Fix val_type annotation for hidden type discovery - Use raw_type string check instead of isinstance for classmethod detection - Access classmethod.__func__ via getattr to avoid partial unknown types - Fix struct base type narrowing in collect_all_type_strings Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b4158d8ca2
commit
cfcb66620a
@ -84,8 +84,9 @@ def collect_all_type_strings(module_data: ModuleData) -> list[str]:
|
|||||||
for var in module_data["variables"]:
|
for var in module_data["variables"]:
|
||||||
all_types.append(map_type(var["type"]))
|
all_types.append(map_type(var["type"]))
|
||||||
for struct in module_data.get("structs", []):
|
for struct in module_data.get("structs", []):
|
||||||
if struct.get("base"):
|
base = struct.get("base")
|
||||||
all_types.append(struct["base"])
|
if base:
|
||||||
|
all_types.append(base)
|
||||||
for prop in struct["properties"]:
|
for prop in struct["properties"]:
|
||||||
all_types.append(prop["type"])
|
all_types.append(prop["type"])
|
||||||
for method in struct["methods"]:
|
for method in struct["methods"]:
|
||||||
@ -538,13 +539,11 @@ def collect_inherited_info(
|
|||||||
if base in by_name:
|
if base in by_name:
|
||||||
base_methods = {m["name"] for m in by_name[base]["methods"]}
|
base_methods = {m["name"] for m in by_name[base]["methods"]}
|
||||||
base_ro_props = {
|
base_ro_props = {
|
||||||
p["name"]
|
p["name"] for p in by_name[base]["properties"] if p["is_readonly"]
|
||||||
for p in by_name[base]["properties"]
|
|
||||||
if p["is_readonly"]
|
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
base_methods = set()
|
base_methods: set[str] = set()
|
||||||
base_ro_props = set()
|
base_ro_props: set[str] = set()
|
||||||
parent = get_inherited(base)
|
parent = get_inherited(base)
|
||||||
cache[name] = _InheritedInfo(
|
cache[name] = _InheritedInfo(
|
||||||
base_methods | parent.methods,
|
base_methods | parent.methods,
|
||||||
@ -755,8 +754,7 @@ def generate_module_stub(
|
|||||||
|
|
||||||
# Add TypeVar if any struct uses Generic[_T]
|
# Add TypeVar if any struct uses Generic[_T]
|
||||||
if any(
|
if any(
|
||||||
"Generic[_T]" in (s.get("base") or "")
|
"Generic[_T]" in (s.get("base") or "") for s in module_data.get("structs", [])
|
||||||
for s in module_data.get("structs", [])
|
|
||||||
):
|
):
|
||||||
parts.append('_T = TypeVar("_T")')
|
parts.append('_T = TypeVar("_T")')
|
||||||
parts.append("")
|
parts.append("")
|
||||||
|
|||||||
@ -333,9 +333,7 @@ def clean_type_str(type_str: str) -> str:
|
|||||||
type_str = type_str.rstrip(":.,")
|
type_str = type_str.rstrip(":.,")
|
||||||
|
|
||||||
# Convert "string in ['X', 'Y', ...]" to Literal["X", "Y", ...]
|
# Convert "string in ['X', 'Y', ...]" to Literal["X", "Y", ...]
|
||||||
str_in_match = re.match(
|
str_in_match = re.match(r"str(?:ing)?\s+in\s+\[([^\]]+)\]", type_str, re.IGNORECASE)
|
||||||
r"str(?:ing)?\s+in\s+\[([^\]]+)\]", type_str, re.IGNORECASE
|
|
||||||
)
|
|
||||||
if str_in_match:
|
if str_in_match:
|
||||||
values = re.findall(r"'([^']+)'", str_in_match.group(1))
|
values = re.findall(r"'([^']+)'", str_in_match.group(1))
|
||||||
if values:
|
if values:
|
||||||
@ -495,9 +493,7 @@ def clean_type_str(type_str: str) -> str:
|
|||||||
# Use \b on both sides to avoid matching inside longer names (e.g. SequenceEntry).
|
# Use \b on both sides to avoid matching inside longer names (e.g. SequenceEntry).
|
||||||
type_str = re.sub(r"\bCallable\b(?!\[)", "Callable[..., object]", type_str)
|
type_str = re.sub(r"\bCallable\b(?!\[)", "Callable[..., object]", type_str)
|
||||||
# Fix Callable[[..., ...], X] or Callable[[object, ...], X] -> Callable[..., X]
|
# Fix Callable[[..., ...], X] or Callable[[object, ...], X] -> Callable[..., X]
|
||||||
type_str = re.sub(
|
type_str = re.sub(r"Callable\[\[[^\]]*\.\.\.[^\]]*\]", "Callable[...", type_str)
|
||||||
r"Callable\[\[[^\]]*\.\.\.[^\]]*\]", "Callable[...", type_str
|
|
||||||
)
|
|
||||||
type_str = re.sub(r"\bdict\b(?!\[)", "dict[str, object]", type_str)
|
type_str = re.sub(r"\bdict\b(?!\[)", "dict[str, object]", type_str)
|
||||||
type_str = re.sub(r"\blist\b(?!\[)", "list[object]", type_str)
|
type_str = re.sub(r"\blist\b(?!\[)", "list[object]", type_str)
|
||||||
type_str = re.sub(r"\btuple\b(?!\[)", "tuple[object, ...]", type_str)
|
type_str = re.sub(r"\btuple\b(?!\[)", "tuple[object, ...]", type_str)
|
||||||
@ -1293,7 +1289,8 @@ def _fix_dunder_signatures(
|
|||||||
# __getitem__: probe with int index to discover element type
|
# __getitem__: probe with int index to discover element type
|
||||||
if name == "__getitem__":
|
if name == "__getitem__":
|
||||||
try:
|
try:
|
||||||
result = instance[0]
|
getitem = getattr(instance, "__getitem__")
|
||||||
|
result = getitem(0)
|
||||||
rtype = _type_name(result)
|
rtype = _type_name(result)
|
||||||
method["return_type"] = rtype
|
method["return_type"] = rtype
|
||||||
method["params"] = [
|
method["params"] = [
|
||||||
@ -1311,7 +1308,8 @@ def _fix_dunder_signatures(
|
|||||||
# __iter__: return Iterator[element_type] based on __getitem__
|
# __iter__: return Iterator[element_type] based on __getitem__
|
||||||
if name == "__iter__":
|
if name == "__iter__":
|
||||||
try:
|
try:
|
||||||
result = instance[0]
|
getitem = getattr(instance, "__getitem__")
|
||||||
|
result = getitem(0)
|
||||||
etype = _type_name(result)
|
etype = _type_name(result)
|
||||||
method["return_type"] = f"Iterator[{etype}]"
|
method["return_type"] = f"Iterator[{etype}]"
|
||||||
method["params"] = []
|
method["params"] = []
|
||||||
@ -1322,7 +1320,8 @@ def _fix_dunder_signatures(
|
|||||||
# __setitem__: refine value type from __getitem__ return type
|
# __setitem__: refine value type from __getitem__ return type
|
||||||
if name == "__setitem__":
|
if name == "__setitem__":
|
||||||
try:
|
try:
|
||||||
result = instance[0]
|
getitem = getattr(instance, "__getitem__")
|
||||||
|
result = getitem(0)
|
||||||
vtype = _type_name(result)
|
vtype = _type_name(result)
|
||||||
method["params"] = [
|
method["params"] = [
|
||||||
{
|
{
|
||||||
@ -1839,13 +1838,13 @@ def introspect_module(module_name: str) -> ModuleData:
|
|||||||
val = getattr(instance, prop["name"])
|
val = getattr(instance, prop["name"])
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
val_type = type(val)
|
val_cls = val.__class__
|
||||||
val_name = val_type.__name__
|
val_name = val_cls.__name__
|
||||||
if hasattr(_builtins_mod, val_name) or val_name in _SKIP_PROP_TYPES:
|
if hasattr(_builtins_mod, val_name) or val_name in _SKIP_PROP_TYPES:
|
||||||
continue
|
continue
|
||||||
# Add the hidden type if not already known
|
# Add the hidden type if not already known
|
||||||
if val_name not in known_struct_names:
|
if val_name not in known_struct_names:
|
||||||
hidden_struct = introspect_class(val_type, module_name)
|
hidden_struct = introspect_class(val_cls, module_name)
|
||||||
# Fix dunders using the live instance (since the type
|
# Fix dunders using the live instance (since the type
|
||||||
# may not be directly constructible)
|
# may not be directly constructible)
|
||||||
dunder_methods = [
|
dunder_methods = [
|
||||||
@ -2512,13 +2511,15 @@ def introspect_rna_types() -> ModuleData:
|
|||||||
raw_type = type(raw).__name__
|
raw_type = type(raw).__name__
|
||||||
# Only pick up C-level methods, not Python-defined ones.
|
# Only pick up C-level methods, not Python-defined ones.
|
||||||
# classmethod wrapping a builtin is C-level (e.g. Space.draw_handler_add)
|
# classmethod wrapping a builtin is C-level (e.g. Space.draw_handler_add)
|
||||||
is_c_classmethod = raw_type == "classmethod_descriptor" or (
|
is_c_classmethod = raw_type == "classmethod_descriptor"
|
||||||
isinstance(raw, classmethod)
|
if not is_c_classmethod and raw_type == "classmethod":
|
||||||
and not hasattr(getattr(raw, "__func__", None), "__code__")
|
# classmethod wrapping a builtin (e.g. Space.draw_handler_add)
|
||||||
)
|
inner = getattr(raw, "__func__", None)
|
||||||
|
is_c_classmethod = inner is not None and not hasattr(inner, "__code__")
|
||||||
if is_c_classmethod:
|
if is_c_classmethod:
|
||||||
obj = getattr(cls, attr_name)
|
bound = getattr(cls, attr_name)
|
||||||
func_data = introspect_callable(obj, attr_name)
|
if callable(bound):
|
||||||
|
func_data = introspect_callable(bound, attr_name)
|
||||||
if func_data:
|
if func_data:
|
||||||
func_data["is_classmethod"] = True
|
func_data["is_classmethod"] = True
|
||||||
struct["methods"].append(func_data)
|
struct["methods"].append(func_data)
|
||||||
@ -2526,7 +2527,9 @@ def introspect_rna_types() -> ModuleData:
|
|||||||
"method_descriptor",
|
"method_descriptor",
|
||||||
"builtin_function_or_method",
|
"builtin_function_or_method",
|
||||||
):
|
):
|
||||||
func_data = introspect_callable(raw, attr_name)
|
obj = getattr(cls, attr_name)
|
||||||
|
if callable(obj):
|
||||||
|
func_data = introspect_callable(obj, attr_name)
|
||||||
if func_data:
|
if func_data:
|
||||||
struct["methods"].append(func_data)
|
struct["methods"].append(func_data)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user