Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Implementation:Bentoml BentoML Internal Types

From Leeroopedia
Knowledge Sources
Domains Type System, Lazy Loading, File I/O
Last Updated 2026-02-13 15:00 GMT

Overview

The Internal Types module defines foundational type aliases, the LazyType utility class for deferred type checking without eager imports, the FileLike wrapper for file-like objects, and the is_compatible_type compatibility checker used throughout BentoML's internals.

Description

This module provides core type infrastructure used extensively across BentoML's codebase. Key components include:

Type aliases and constants:

  • MetadataType: A recursive TypeAlias for metadata values (str, bytes, bool, int, float, complex, datetime variants, and nested lists/tuples/dicts).
  • MetadataDict: Dict[str, MetadataType].
  • JSONSerializable: Union of JSON-compatible types (str, int, float, bool, None, list, dict).
  • PathType: str | os.PathLike[str].
  • ModelSignatureDict: TypedDict for model signature configuration (batchable, batch_dim, input_spec, output_spec).
  • LifecycleHook: Callable type for Starlette lifecycle hooks.
  • BATCH_HEADER, HEADER_CHARSET, JSON_CHARSET: Protocol constants.
  • AnyType: Union of Type[Any], UnionType, and LazyType[Any] (runtime fallback to Any).

LazyType[T] (Generic class): A deferred type reference that resolves classes lazily. Solves three key conflicts:

  • Lazy isinstance: LazyType("numpy.ndarray").isinstance(obj) avoids importing numpy at check time. The class is only resolved from sys.modules when needed (without triggering an import unless import_module=True).
  • Type narrowing: Works with TypeGuard[T] (PEP 647) so that LazyType["NDArray"]("numpy.ndarray").isinstance(obj) narrows the type for type checkers.
  • Type comparison: LazyType("numpy.ndarray") == numpy.ndarray works by comparing module and qualname strings. Hashable, so usable as dictionary keys.

Construction supports three forms:

  • LazyType("numpy", "ndarray"): Module and qualname as separate strings.
  • LazyType("numpy.ndarray"): Dotted path auto-split on last dot.
  • LazyType(numpy.ndarray): From an already-imported class.

Methods:

  • get_class(import_module=True): Resolves and returns the actual class, optionally importing the module.
  • isinstance(obj): Checks isinstance without importing (returns False if module not loaded).
  • issubclass(klass): Checks issubclass without importing.
  • from_type(cls, typ_): Factory that wraps a raw type in LazyType or returns an existing LazyType.
  • __instancecheck__: Enables isinstance(obj, LazyType(...)) syntax.

is_compatible_type(t1, t2): Checks whether two types could share instances. Handles Union types by recursing into their args. Resolves LazyTypes. For concrete types, checks mutual subclass relationship. Returns True for unsupported cases as a safe default.

FileLike[AnyStr] (dataclass, extends io.IOBase): A generic wrapper for file-like objects that adds a custom name property. Delegates all IO operations (read, write, seek, tell, close, etc.) to the wrapped _wrapped object. Supports both text and binary modes via the AnyStr type variable.

Usage

LazyType is used extensively in IO descriptors and runner containers for type checking without eagerly importing heavy dependencies like NumPy, Pandas, or PIL. FileLike is used for wrapping file objects with custom names. The type aliases provide consistent typing across the codebase.

Code Reference

Source Location

Signature

class LazyType(t.Generic[T]):
    module: str
    qualname: str

    @t.overload
    def __init__(self, module_or_cls: str, qualname: str) -> None: ...
    @t.overload
    def __init__(self, module_or_cls: t.Type[T]) -> None: ...
    @t.overload
    def __init__(self, module_or_cls: str) -> None: ...

    @classmethod
    def from_type(cls, typ_: t.Union[LazyType[T], t.Type[T]]) -> LazyType[T]: ...
    def get_class(self, import_module: bool = True) -> t.Type[T]: ...
    def isinstance(self, obj: t.Any) -> t.TypeGuard[T]: ...
    def issubclass(self, klass: type) -> bool: ...


def is_compatible_type(t1: AnyType, t2: AnyType) -> bool: ...


@dataclass(frozen=False)
class FileLike(t.Generic[t.AnyStr], io.IOBase):
    _wrapped: t.IO[t.AnyStr]
    _name: str

    def read(self, size: int = -1) -> t.AnyStr: ...
    def write(self, s: t.AnyStr) -> int: ...
    def seek(self, offset: int, whence: int = io.SEEK_SET) -> int: ...
    # ... (all standard IO methods delegated to _wrapped)

Import

from bentoml._internal.types import LazyType
from bentoml._internal.types import FileLike
from bentoml._internal.types import is_compatible_type
from bentoml._internal.types import MetadataDict
from bentoml._internal.types import JSONSerializable

I/O Contract

Inputs (LazyType)

Name Type Required Description
module_or_cls str or Type[T] Yes Module path string (e.g., "numpy.ndarray"), module and qualname pair, or an actual class reference.
qualname str or None No Class qualname when module is provided as a separate string.

Outputs (LazyType)

Name Type Description
LazyType[T] LazyType A lazy type reference that can check isinstance/issubclass without importing and resolves to the actual class on demand.

Inputs (FileLike)

Name Type Required Description
_wrapped IO[AnyStr] Yes The underlying file-like object to delegate operations to.
_name str Yes Custom name for the file-like object.

Outputs (FileLike)

Name Type Description
FileLike[AnyStr] FileLike A file-like wrapper that delegates all IO operations to the wrapped object with a custom name.

Usage Examples

from bentoml._internal.types import LazyType, FileLike, is_compatible_type
import io

# LazyType usage - isinstance without importing numpy
obj = [1, 2, 3]
if LazyType("numpy.ndarray").isinstance(obj):
    print("It's an ndarray")
else:
    print("Not an ndarray")

# LazyType as dictionary key
HANDLER_MAP = {
    LazyType("numpy.ndarray"): lambda x: "ndarray_handler",
    LazyType("pandas.DataFrame"): lambda x: "dataframe_handler",
}

# LazyType comparison
import numpy as np
assert LazyType("numpy", "ndarray") == np.ndarray

# is_compatible_type check
assert is_compatible_type(int, int) is True
assert is_compatible_type(int, str) is False

# FileLike wrapper
buffer = io.BytesIO(b"hello world")
f = FileLike(_wrapped=buffer, _name="my_file.bin")
assert f.name == "my_file.bin"
data = f.read()  # b"hello world"

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment