Source code for simvx.core.assets.sources.pkg

"""Package-resource source: resolves ``pkg://<package>/<path>`` URIs."""

from __future__ import annotations

import importlib.resources
from collections.abc import Iterable
from importlib.resources.abc import Traversable


[docs] class PkgSource: """Reads bytes from a Python package via :mod:`importlib.resources`. URI form: ``pkg://<package>/<path>`` where path may contain forward slashes for nested files (``pkg://game/textures/player.png``). """ scheme = "pkg" def _resolve(self, uri: str) -> Traversable: package, _, path = self._split(uri) root = importlib.resources.files(package) if not path: return root node = root for part in path.split("/"): if not part: continue node = node / part return node @staticmethod def _split(uri: str) -> tuple[str, str, str]: if not uri.startswith("pkg://"): raise ValueError(f"PkgSource expects pkg:// URI, got {uri!r}") rest = uri[len("pkg://"):] if "/" in rest: package, path = rest.split("/", 1) else: package, path = rest, "" return package, "/", path
[docs] def read_bytes(self, uri: str) -> bytes: return self._resolve(uri).read_bytes()
[docs] def version(self, uri: str) -> str | None: # Package resources are immutable across a Python session; no version hint. return None
[docs] def list(self, uri: str) -> Iterable[str]: node = self._resolve(uri) if not node.is_dir(): raise NotADirectoryError(f"PkgSource.list expects a directory URI, got {uri!r}") package, _, path = self._split(uri) prefix = f"pkg://{package}/" + (f"{path}/" if path else "") for child in node.iterdir(): yield prefix + child.name