Skip to content

liblaf.melon.io.abc

Reusable dispatchers for readers, writers, and converters.

Classes:

  • AbstractConverter

    Callable that converts one object into another mesh representation.

  • AbstractReader

    Callable that loads an object from a path.

  • AbstractWriter

    Callable that writes an object to a path.

  • ConverterDispatcher

    Single-dispatch conversion registry with identity conversion built in.

  • ReaderDispatcher

    Dispatch readers by file suffix with an optional fallback reader.

  • WriterDispatcher

    Dispatch writers first by file suffix and then by object type.

Attributes:

save module-attribute

Write registered mesh and scene objects to disk based on path suffix.

AbstractConverter

Bases: Protocol


              flowchart TD
              liblaf.melon.io.abc.AbstractConverter[AbstractConverter]

              

              click liblaf.melon.io.abc.AbstractConverter href "" "liblaf.melon.io.abc.AbstractConverter"
            

Callable that converts one object into another mesh representation.

Methods:

__call__

__call__(obj: F, /, **kwargs) -> T
Source code in src/liblaf/melon/io/abc/_converter.py
def __call__(self, obj: F, /, **kwargs) -> T: ...

AbstractReader

Bases: Protocol


              flowchart TD
              liblaf.melon.io.abc.AbstractReader[AbstractReader]

              

              click liblaf.melon.io.abc.AbstractReader href "" "liblaf.melon.io.abc.AbstractReader"
            

Callable that loads an object from a path.

Methods:

__call__

__call__(path: Path, /, **kwargs) -> T
Source code in src/liblaf/melon/io/abc/_reader.py
def __call__(self, path: Path, /, **kwargs) -> T: ...

AbstractWriter

Bases: Protocol


              flowchart TD
              liblaf.melon.io.abc.AbstractWriter[AbstractWriter]

              

              click liblaf.melon.io.abc.AbstractWriter href "" "liblaf.melon.io.abc.AbstractWriter"
            

Callable that writes an object to a path.

Methods:

__call__

__call__(obj: T, path: Path, /, **kwargs) -> None
Source code in src/liblaf/melon/io/abc/_writer.py
def __call__(self, obj: T, path: Path, /, **kwargs) -> None: ...

ConverterDispatcher

Single-dispatch conversion registry with identity conversion built in.

The target type is registered as an identity conversion, so callers can pass through objects that are already in the requested representation.

Examples:

>>> converter = ConverterDispatcher(str)
>>> converter("mesh")
'mesh'
>>> @converter.register(int)
... def _from_int(obj, /, **kwargs):
...     return str(obj)
>>> converter(42)
'42'

Parameters:

  • to_type (type[T]) –

    Target type returned unchanged when the input already has that runtime type.

  • registry (_SingleDispatchCallable[T], default: <dynamic> ) –

    Underlying functools.singledispatch registry.

Methods:

Attributes:

  • registry (_SingleDispatchCallable[T]) –

    Underlying functools.singledispatch registry.

  • to_type (type[T]) –

    Target type returned unchanged when the input already has that runtime type.

registry class-attribute instance-attribute

registry: _SingleDispatchCallable[T] = field(
    default=Factory(_default_registry, takes_self=True)
)

Underlying functools.singledispatch registry.

to_type instance-attribute

to_type: type[T]

Target type returned unchanged when the input already has that runtime type.

__call__

__call__(obj: Any, /, **kwargs) -> T
Source code in src/liblaf/melon/io/abc/_converter.py
def __call__(self, obj: Any, /, **kwargs) -> T:
    return self.registry(obj, **kwargs)

register

register[F](
    cls: _RegType, converter: AbstractConverter[F, T]
) -> AbstractConverter[F, T]
register[F](
    cls: _RegType, converter: None = None
) -> Callable[
    [AbstractConverter[F, T]], AbstractConverter[F, T]
]
Source code in src/liblaf/melon/io/abc/_converter.py
def register[F](
    self, cls: _RegType, converter: AbstractConverter[F, T] | None = None
) -> Callable[..., Any]:
    if converter is None:
        return functools.partial(self.register, cls)
    self.registry.register(cls, converter)
    return converter

ReaderDispatcher

Dispatch readers by file suffix with an optional fallback reader.

Raises:

  • KeyError

    If the path suffix is unknown and no fallback reader exists.

Attributes:

Parameters:

  • to_type (type[T]) –
  • fallback (AbstractReader[T] | None, default: None ) –
  • registry (dict[str, AbstractReader[T]], default: <class 'dict'> ) –

    dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

Methods:

fallback class-attribute instance-attribute

fallback: AbstractReader[T] | None = None

registry class-attribute instance-attribute

registry: dict[str, AbstractReader[T]] = field(
    factory=dict
)

to_type instance-attribute

to_type: type[T]

__call__

__call__(path: StrPath, /, **kwargs) -> T
Source code in src/liblaf/melon/io/abc/_reader.py
def __call__(self, path: StrPath, /, **kwargs) -> T:
    path: Path = Path(path)
    reader: AbstractReader[T] | None = self.registry.get(path.suffix, self.fallback)
    if reader is None:
        raise KeyError(path.suffix)
    return reader(path, **kwargs)

register

register(
    suffixes: Iterable[str], reader: AbstractReader[T]
) -> AbstractReader[T]
register(
    suffixes: Iterable[str], reader: None = None
) -> Callable[[AbstractReader[T]], AbstractReader[T]]
Source code in src/liblaf/melon/io/abc/_reader.py
def register(
    self, suffixes: Iterable[str], reader: AbstractReader[T] | None = None
) -> Callable[..., Any]:
    if reader is None:
        return functools.partial(self.register, suffixes)
    for s in suffixes:
        self.registry[s] = reader
    return reader

register_fallback

register_fallback(
    reader: AbstractReader[T],
) -> AbstractReader[T]
Source code in src/liblaf/melon/io/abc/_reader.py
def register_fallback(self, reader: AbstractReader[T]) -> AbstractReader[T]:
    self.fallback = reader
    return reader

WriterDispatcher

Dispatch writers first by file suffix and then by object type.

Registered writers receive a pathlib.Path. Parent directories are created before the writer is called, which keeps concrete writer implementations focused on serialization.

Raises:

  • KeyError

    If no writer registry exists for the path suffix.

  • NotImplementedError

    If the suffix exists but the object type is not registered for that suffix.

Parameters:

  • registry (dict[str, _SingleDispatchCallable[None]], default: <class 'dict'> ) –

    dict() -> new empty dictionary dict(mapping) -> new dictionary initialized from a mapping object's (key, value) pairs dict(iterable) -> new dictionary initialized as if via: d = {} for k, v in iterable: d[k] = v dict(**kwargs) -> new dictionary initialized with the name=value pairs in the keyword argument list. For example: dict(one=1, two=2)

Methods:

Attributes:

registry class-attribute instance-attribute

registry: dict[str, _SingleDispatchCallable[None]] = field(
    factory=dict
)

__call__

__call__(obj: T, path: StrPath, /, **kwargs) -> None
Source code in src/liblaf/melon/io/abc/_writer.py
def __call__(self, obj: T, path: StrPath, /, **kwargs) -> None:
    path: Path = Path(path)
    writer: _SingleDispatchCallable[None] = self.registry[path.suffix]
    path.parent.mkdir(parents=True, exist_ok=True)
    return writer(obj, path, **kwargs)

register

register(
    cls: _RegType,
    suffixes: Iterable[str],
    writer: AbstractWriter[T],
) -> AbstractWriter[T]
register(
    cls: _RegType,
    suffixes: Iterable[str],
    writer: None = None,
) -> Callable[[AbstractWriter[T]], AbstractWriter[T]]
Source code in src/liblaf/melon/io/abc/_writer.py
def register(
    self,
    cls: _RegType,
    suffixes: Iterable[str],
    writer: AbstractWriter[T] | None = None,
) -> Callable[..., Any]:
    if writer is None:
        return functools.partial(self.register, cls, suffixes)
    for suffix in suffixes:
        if suffix not in self.registry:
            self.registry[suffix] = functools.singledispatch(_default_writer)
        self.registry[suffix].register(cls, writer)
    return writer