showbase: Annotate `VFSImporter` functions (#1764)

This commit is contained in:
WMOkiishi 2025-08-02 08:42:58 -06:00 committed by GitHub
parent fe65114cd7
commit f00cec70e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 25 additions and 20 deletions

View File

@ -5,9 +5,11 @@ Calling the :func:`register()` function to register the import hooks should be
sufficient to enable this functionality.
"""
from __future__ import annotations
__all__ = ['register']
from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem
from panda3d.core import Filename, VirtualFile, VirtualFileSystem, VirtualFileMountSystem
from panda3d.core import OFileStream, copy_stream
import sys
import marshal
@ -16,14 +18,17 @@ import atexit
from importlib.abc import Loader, SourceLoader
from importlib.util import MAGIC_NUMBER, decode_source
from importlib.machinery import ModuleSpec, EXTENSION_SUFFIXES, BYTECODE_SUFFIXES
from types import ModuleType
from typing import Any
vfs = VirtualFileSystem.get_global_ptr()
def _make_spec(fullname, loader, *, is_package):
def _make_spec(fullname: str, loader: VFSLoader, *, is_package: bool) -> ModuleSpec:
filename = loader._vfile.get_filename()
spec = ModuleSpec(fullname, loader, origin=filename.to_os_specific(), is_package=is_package)
if is_package:
assert spec.submodule_search_locations is not None
spec.submodule_search_locations.append(Filename(filename.get_dirname()).to_os_specific())
spec.has_location = True
return spec
@ -35,16 +40,15 @@ class VFSFinder:
which allows loading Python source files from mounted .mf files
(among other places). """
def __init__(self, path):
def __init__(self, path: str) -> None:
self.path = path
def find_spec(self, fullname, path, target=None):
if path is None:
path = self.path
def find_spec(self, fullname: str, target: ModuleType | None = None) -> ModuleSpec | None:
#print(f"find_spec({fullname}), dir_path = {dir_path}", file=sys.stderr)
basename = fullname.split('.')[-1]
filename = Filename(Filename.from_os_specific(path), basename)
filename = Filename(Filename.from_os_specific(self.path), basename)
loader: VFSLoader
# First, look for Python files.
vfile = vfs.get_file(filename + '.py', True)
@ -84,6 +88,7 @@ class VFSFinder:
# Consider a namespace package.
if vfs.is_directory(filename):
spec = ModuleSpec(fullname, VFSNamespaceLoader(), is_package=True)
assert spec.submodule_search_locations is not None
spec.submodule_search_locations.append(filename.to_os_specific())
return spec
@ -92,7 +97,7 @@ class VFSFinder:
class VFSLoader(Loader):
def __init__(self, fullname, vfile):
def __init__(self, fullname: str, vfile: VirtualFile) -> None:
self.name = fullname
self._vfile = vfile
@ -105,22 +110,22 @@ class VFSLoader(Loader):
tail_name = fullname.rpartition('.')[2]
return filename_base == '__init__' and tail_name != '__init__'
def create_module(self, spec):
def create_module(self, spec: ModuleSpec) -> ModuleType | None:
"""Use default semantics for module creation."""
def exec_module(self, module):
def exec_module(self, module: ModuleType) -> None:
"""Execute the module."""
code = self.get_code(module.__name__)
code = self.get_code(module.__name__) # type: ignore[attr-defined]
exec(code, module.__dict__)
def get_filename(self, fullname):
def get_filename(self, fullname: str) -> str:
if fullname is not None and self.name != fullname:
raise ImportError
return self._vfile.get_filename().to_os_specific()
@staticmethod
def get_data(path):
def get_data(path: str) -> bytes:
vfile = vfs.get_file(Filename.from_os_specific(path))
if vfile:
return vfile.read_file(True)
@ -128,7 +133,7 @@ class VFSLoader(Loader):
raise OSError
@staticmethod
def path_stats(path):
def path_stats(path: str) -> dict[str, Any]:
vfile = vfs.get_file(Filename.from_os_specific(path))
if vfile:
return {'mtime': vfile.get_timestamp(), 'size': vfile.get_file_size()}
@ -231,11 +236,11 @@ class VFSExtensionLoader(VFSLoader):
return None
class VFSNamespaceLoader:
def create_module(self, spec):
class VFSNamespaceLoader(Loader):
def create_module(self, spec: ModuleSpec) -> ModuleType | None:
"""Use default semantics for module creation."""
def exec_module(self, module):
def exec_module(self, module: ModuleType) -> None:
pass
def is_package(self, fullname):
@ -248,7 +253,7 @@ class VFSNamespaceLoader:
return compile('', '<string>', 'exec', dont_inherit=True)
def _path_hook(entry):
def _path_hook(entry: str) -> VFSFinder:
# If this is a directory in the VFS, create a VFSFinder for this entry.
vfile = vfs.get_file(Filename.from_os_specific(entry), False)
if vfile and vfile.is_directory() and not isinstance(vfile.get_mount(), VirtualFileMountSystem):
@ -259,7 +264,7 @@ def _path_hook(entry):
_registered = False
def register():
def register() -> None:
""" Register the VFSFinder on the path_hooks, if it has not
already been registered, so that future Python import statements
will vector through here (and therefore will take advantage of