Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/kernels/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,24 @@ def universal_build_variant() -> str:
return "torch-universal"


# Metaclass to allow overriding the `__repr__` method for kernel modules.
class _KernelModuleMeta(type):
def __repr__(self):
return "<class 'kernel_module'>"


# Custom module type to identify dynamically loaded kernel modules.
# Using a subclass lets us distinguish these from regular imports.
class _KernelModuleType(ModuleType, metaclass=_KernelModuleMeta):
"""Marker class for modules loaded dynamically from a path."""

module_name: str
is_kernel: bool = True

def __repr__(self):
return f"<kernel_module '{self.module_name}' from '{self.__file__}'>"


def import_from_path(module_name: str, file_path: Path) -> ModuleType:
# We cannot use the module name as-is, after adding it to `sys.modules`,
# it would also be used for other imports. So, we make a module name that
Expand All @@ -84,6 +102,9 @@ def import_from_path(module_name: str, file_path: Path) -> ModuleType:
module = importlib.util.module_from_spec(spec)
if module is None:
raise ImportError(f"Cannot load module {module_name} from spec")
module.__class__ = _KernelModuleType
Copy link
Member

@danieldk danieldk Aug 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I am a bit worried that there is some module graph processing code that directly matches on ModuleType and will break. Maybe it's safer to directly inject the attributes/methods for now without changing the class (we can always do it in the future without additional breakage)?

Maybe it's also worth storing the LayerRepository/LocalRepository besides the module name , since that provides full information about where the module comes from.

We also need to add to the spec that any method_name and is_kernel attributes are overridden and probably document this attributes.

assert isinstance(module, _KernelModuleType) # for mypy type checking
module.module_name = module_name
sys.modules[module_name] = module
spec.loader.exec_module(module) # type: ignore
return module
Expand Down
Loading