script_bindings(python): Add type around CG class in codegen.py (#38845)

Add type around CG class for code generatio Web IDL in codegen.py


Testing: *Describe how this pull request is tested or why it doesn't
require tests*
Fixes: *Link to an issue this pull requests fixes or remove this line if
there is no issue*

---------

Signed-off-by: Jerens Lensun <jerensslensun@gmail.com>
Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
Jerens Lensun 2025-08-29 12:32:14 +08:00 committed by GitHub
parent 20e955277a
commit 00c1f79a1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 297 additions and 208 deletions

File diff suppressed because it is too large Load diff

View file

@ -8,23 +8,31 @@ from __future__ import annotations
import functools import functools
import os import os
from typing import Any from typing import Any, TypeVar
from WebIDL import ( from WebIDL import (
IDLExternalInterface, IDLExternalInterface,
IDLSequenceType, IDLSequenceType,
IDLWrapperType, IDLWrapperType,
WebIDLError, WebIDLError,
IDLEnum,
IDLObject, IDLObject,
IDLObjectWithIdentifier,
IDLType, IDLType,
IDLInterface, IDLTypedef,
IDLInterfaceOrNamespace,
IDLDictionary, IDLDictionary,
IDLCallback, IDLCallback,
IDLAttribute, IDLAttribute,
IDLMethod, IDLMethod,
) )
TargetType = TypeVar('TargetType')
def assert_type(object: Any, cls: type[TargetType]) -> TargetType:
assert isinstance(object, cls)
return object
FilterItemsType = TypeVar('FilterItemsType', bound=IDLObjectWithIdentifier)
class Configuration: class Configuration:
""" """
Represents global configuration state based on IDL parse data and Represents global configuration state based on IDL parse data and
@ -35,9 +43,13 @@ class Configuration:
dictConfig: dict[str, Any] dictConfig: dict[str, Any]
unionConfig: dict[str, Any] unionConfig: dict[str, Any]
descriptors: list[Descriptor] descriptors: list[Descriptor]
interfaces: dict[str, IDLInterface] interfaces: dict[str, IDLInterfaceOrNamespace]
enums: list[IDLEnum]
typedefs: list[IDLTypedef]
dictionaries: list[IDLDictionary]
callbacks: list[IDLCallback]
def __init__(self, filename: str, parseData: list[IDLInterface]) -> None: def __init__(self, filename: str, parseData: list[IDLObjectWithIdentifier]) -> None:
# Read the configuration file. # Read the configuration file.
glbl = {} glbl = {}
exec(compile(open(filename).read(), filename, 'exec'), glbl) exec(compile(open(filename).read(), filename, 'exec'), glbl)
@ -64,6 +76,7 @@ class Configuration:
continue continue
iface = thing iface = thing
assert isinstance(iface, IDLInterfaceOrNamespace)
self.interfaces[iface.identifier.name] = iface self.interfaces[iface.identifier.name] = iface
if iface.identifier.name not in config: if iface.identifier.name not in config:
entry = {} entry = {}
@ -83,10 +96,10 @@ class Configuration:
if d.interface.identifier.name == interfaceName] if d.interface.identifier.name == interfaceName]
descriptor.uniqueImplementation = len(otherDescriptors) == 1 descriptor.uniqueImplementation = len(otherDescriptors) == 1
self.enums = [e for e in parseData if e.isEnum()] self.enums = [assert_type(e, IDLEnum) for e in parseData if e.isEnum()]
self.typedefs = [e for e in parseData if e.isTypedef()] self.typedefs = [assert_type(e, IDLTypedef) for e in parseData if e.isTypedef()]
self.dictionaries = [d for d in parseData if d.isDictionary()] self.dictionaries = [assert_type(d, IDLDictionary) for d in parseData if d.isDictionary()]
self.callbacks = [c for c in parseData if self.callbacks = [assert_type(c, IDLCallback) for c in parseData if
c.isCallback() and not c.isInterface()] c.isCallback() and not c.isInterface()]
# Keep the descriptor list sorted for determinism. # Keep the descriptor list sorted for determinism.
@ -94,10 +107,10 @@ class Configuration:
return (x > y) - (x < y) return (x > y) - (x < y)
self.descriptors.sort(key=functools.cmp_to_key(lambda x, y: cmp(x.name, y.name))) self.descriptors.sort(key=functools.cmp_to_key(lambda x, y: cmp(x.name, y.name)))
def getInterface(self, ifname: str) -> IDLInterface: def getInterface(self, ifname: str) -> IDLInterfaceOrNamespace:
return self.interfaces[ifname] return self.interfaces[ifname]
def getDescriptors(self, **filters: IDLInterface) -> list[Descriptor]: def getDescriptors(self, **filters: IDLInterfaceOrNamespace) -> list[Descriptor]:
"""Gets the descriptors that match the given filters.""" """Gets the descriptors that match the given filters."""
curr = self.descriptors curr = self.descriptors
for key, val in filters.items(): for key, val in filters.items():
@ -134,17 +147,17 @@ class Configuration:
curr = [x for x in curr if getter(x) == val] curr = [x for x in curr if getter(x) == val]
return curr return curr
def getEnums(self, webIDLFile: str) -> list[IDLInterface]: def getEnums(self, webIDLFile: str) -> list[IDLEnum]:
return [e for e in self.enums if e.filename == webIDLFile] return [e for e in self.enums if e.filename == webIDLFile]
def getEnumConfig(self, name: str) -> dict[str, Any]: def getEnumConfig(self, name: str) -> dict[str, Any]:
return self.enumConfig.get(name, {}) return self.enumConfig.get(name, {})
def getTypedefs(self, webIDLFile: str) -> list[IDLInterface]: def getTypedefs(self, webIDLFile: str) -> list[IDLTypedef]:
return [e for e in self.typedefs if e.filename == webIDLFile] return [e for e in self.typedefs if e.filename == webIDLFile]
@staticmethod @staticmethod
def _filterForFile(items: list[IDLInterface], webIDLFile: str = "") -> list[IDLInterface]: def _filterForFile(items: list[FilterItemsType], webIDLFile: str = "") -> list[FilterItemsType]:
"""Gets the items that match the given filters.""" """Gets the items that match the given filters."""
if not webIDLFile: if not webIDLFile:
return items return items
@ -154,13 +167,13 @@ class Configuration:
def getUnionConfig(self, name: str) -> dict[str, Any]: def getUnionConfig(self, name: str) -> dict[str, Any]:
return self.unionConfig.get(name, {}) return self.unionConfig.get(name, {})
def getDictionaries(self, webIDLFile: str = "") -> list[IDLInterface]: def getDictionaries(self, webIDLFile: str = "") -> list[IDLDictionary]:
return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile) return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile)
def getDictConfig(self, name: str) -> dict[str, Any]: def getDictConfig(self, name: str) -> dict[str, Any]:
return self.dictConfig.get(name, {}) return self.dictConfig.get(name, {})
def getCallbacks(self, webIDLFile: str = "") -> list[IDLInterface]: def getCallbacks(self, webIDLFile: str = "") -> list[IDLCallback]:
return self._filterForFile(self.callbacks, webIDLFile=webIDLFile) return self._filterForFile(self.callbacks, webIDLFile=webIDLFile)
def getDescriptor(self, interfaceName: str) -> Descriptor: def getDescriptor(self, interfaceName: str) -> Descriptor:
@ -214,10 +227,10 @@ class Descriptor(DescriptorProvider):
""" """
Represents a single descriptor for an interface. See Bindings.conf. Represents a single descriptor for an interface. See Bindings.conf.
""" """
interface: IDLInterface interface: IDLInterfaceOrNamespace
uniqueImplementation: bool uniqueImplementation: bool
def __init__(self, config: Configuration, interface: IDLInterface, desc: dict[str, Any]) -> None: def __init__(self, config: Configuration, interface: IDLInterfaceOrNamespace, desc: dict[str, Any]) -> None:
DescriptorProvider.__init__(self, config) DescriptorProvider.__init__(self, config)
self.interface = interface self.interface = interface
@ -318,7 +331,7 @@ class Descriptor(DescriptorProvider):
self.hasDefaultToJSON = True self.hasDefaultToJSON = True
if self.concrete: if self.concrete:
iface: IDLInterface | None = self.interface iface: IDLInterfaceOrNamespace | None = self.interface
while iface: while iface:
for m in iface.members: for m in iface.members:
if not m.isMethod(): if not m.isMethod():
@ -374,7 +387,7 @@ class Descriptor(DescriptorProvider):
else: else:
assert isinstance(config, str) assert isinstance(config, str)
if config == '*': if config == '*':
iface: IDLInterface | None = self.interface iface: IDLInterfaceOrNamespace | None = self.interface
while iface: while iface:
add('all', [m.name for m in iface.members], attribute) add('all', [m.name for m in iface.members], attribute)
iface = iface.parent iface = iface.parent
@ -401,7 +414,7 @@ class Descriptor(DescriptorProvider):
# Build the prototype chain. # Build the prototype chain.
self.prototypeChain = [] self.prototypeChain = []
parent: IDLInterface | None = interface parent: IDLInterfaceOrNamespace | None = interface
while parent: while parent:
self.prototypeChain.insert(0, parent.identifier.name) self.prototypeChain.insert(0, parent.identifier.name)
parent = parent.parent parent = parent.parent
@ -543,7 +556,7 @@ def getTypesFromDescriptor(descriptor: Descriptor) -> list[IDLType]:
return types return types
def getTypesFromDictionary(dictionary: IDLDictionary) -> list[IDLType]: def getTypesFromDictionary(dictionary: IDLWrapperType | IDLDictionary) -> list[IDLType]:
""" """
Get all member types for this dictionary Get all member types for this dictionary
""" """