The GitHub Actions job "CI" on tvm-ffi.git/main has succeeded. Run started by GitHub user junrushao (triggered by junrushao).
Head commit for run: b58c2e3d7deadbd60c7480f5c84633966260bc9a / Junru Shao <[email protected]> feat(stubgen): Package generation with `--init-*` flags (#295) This commit adds explicit `--init-*` flags so that packages can be bootstrapped cleanly from a single command. **Usage.** for the my-ffi-extension example): ``` tvm-ffi-stubgen examples/packaging/python \ --dlls examples/packaging/build/libmy_ffi_extension.dylib \ --init-pypkg my-ffi-extension \ --init-lib my_ffi_extension \ --init-prefix "my_ffi_extension." ``` What each flag means: - `PATH`: the files/directories to scan; the directory of the first entry becomes the root where `_ffi_api.py`/`__init__.py` stubs are generated. - `--dlls`: preload the built shared library so global function/type metadata is available (here the dylib from the packaging example build). - `--init-pypkg`: the published Python package name (wheel/sdist name), used in the loader string. - `--init-lib`: the CMake target/basename of the shared library (`lib<init-lib>.so`/`.dylib`/`.dll`). - `--init-prefix`: registry prefix to include when generating globals/objects (e.g. `my_ffi_extension.`). **Behavior**. - The tool creates missing `_ffi_api.py` and `__init__.py` under the derived path/prefix. - It scans existing stub blocks, honors ty-map and imports, and adds an `__all__` section without duplication on reruns. - Re-running the command is idempotent: previously generated sections are detected and not appended again. **Example**. See `my_ffi_extension/__init__.py` and `my_ffi_extension/_ffi_api.py`. **How to use this tool** ``` >>> tvm-ffi-stubgen --help usage: tvm-ffi-stubgen [-h] [--imports IMPORTS] [--dlls LIBS] [--init-pypkg INIT_PYPKG] [--init-lib INIT_LIB] [--init-prefix INIT_PREFIX] [--indent INDENT] [--verbose] [--dry-run] [PATH ...] Generate type stubs for TVM FFI extensions. In `--init-*` mode, it generates missing `_ffi_api.py` and `__init__.py` files, based on the registered global functions and object types in the loaded libraries. In normal mode, it processes the given files/directories in-place, generating type stubs inside special `tvm-ffi-stubgen` blocks. Scroo down for more details. positional arguments: PATH Files or directories to process. Directories are scanned recursively; only .py and .pyi files are modified. Use tvm-ffi-stubgen markers to select where stubs are generated. (default: None) options: -h, --help show this help message and exit --imports IMPORTS Additional imports to load before generation, separated by ';' (e.g. 'pkgA;pkgB.submodule'). (default: ) --dlls LIBS Shared libraries to preload before generation (e.g. TVM runtime or your extension), separated by ';'. This ensures global function and object metadata is available. Platform-specific suffixes like .so/.dylib/.dll are supported. (default: ) --init-pypkg INIT_PYPKG Python package name to generate stubs for (e.g. apache-tvm-ffi). Required together with --init-lib, --init-path, and --init-prefix. (default: ) --init-lib INIT_LIB CMake target that produces the shared library to load for stub generation (e.g. tvm_ffi_shared). Required together with --init-pypkg and --init-prefix. (default: ) --init-prefix INIT_PREFIX Global function/object prefix to include when generating stubs (e.g. tvm_ffi.). Required together with --init-pypkg and --init-lib. (default: ) --indent INDENT Extra spaces added inside each generated block, relative to the indentation of the corresponding '# tvm-ffi-stubgen(begin):' line. (default: 4) --verbose Print a unified diff of changes to each file. This is useful for debugging or previewing changes before applying them. (default: False) --dry-run Don't write changes to files. This is useful for previewing changes without modifying any files. (default: False) ======== Examples ======== # Single file tvm-ffi-stubgen python/tvm_ffi/_ffi_api.py # Recursively scan directories tvm-ffi-stubgen python/tvm_ffi examples/packaging/python/my_ffi_extension # Preload extension libraries tvm-ffi-stubgen --dlls build/libmy_ext.so;build/libmy_2nd_ext.so my_pkg/_ffi_api.py # Package-level init (my-ffi-extension) tvm-ffi-stubgen examples/packaging/python \ --dlls examples/packaging/build/libmy_ffi_extension.dylib \ --init-pypkg my-ffi-extension \ --init-lib my_ffi_extension \ --init-prefix "my_ffi_extension." ===================== Syntax of stub blocks ===================== Global functions ~~~~~~~~~~~~~~~~ ``` # tvm-ffi-stubgen(begin): global/<registry-prefix>@<import-from (default: tvm_ffi)> # tvm-ffi-stubgen(end) ``` Generates TYPE_CHECKING-only stubs for functions in the global registry under the prefix. Example: ``` # tvm-ffi-stubgen(begin): global/[email protected] # fmt: off _FFI_INIT_FUNC("ffi", __name__) if TYPE_CHECKING: def Array(*args: Any) -> Any: ... def ArrayGetItem(_0: Sequence[Any], _1: int, /) -> Any: ... def ArraySize(_0: Sequence[Any], /) -> int: ... def Bytes(_0: bytes, /) -> bytes: ... ... def StructuralHash(_0: Any, _1: bool, _2: bool, /) -> int: ... def SystemLib(*args: Any) -> Any: ... def ToJSONGraph(_0: Any, _1: Any, /) -> Any: ... def ToJSONGraphString(_0: Any, _1: Any, /) -> str: ... # fmt: on # tvm-ffi-stubgen(end) ``` Objects ~~~~~~~ ``` # tvm-ffi-stubgen(begin): object/<type_key> # tvm-ffi-stubgen(end) ``` Generates fields/methods for a class defined using TVM-FFI Object APIs. Example: ``` @register_object("ffi.reflection.AccessPath") class AccessPath(tvm_ffi.Object): # tvm-ffi-stubgen(begin): object/ffi.reflection.AccessPath # fmt: off parent: Object | None step: AccessStep | None depth: int if TYPE_CHECKING: @staticmethod def _root() -> AccessPath: ... def _extend(self, _1: AccessStep, /) -> AccessPath: ... def _attr(self, _1: str, /) -> AccessPath: ... def _array_item(self, _1: int, /) -> AccessPath: ... def _map_item(self, _1: Any, /) -> AccessPath: ... def _attr_missing(self, _1: str, /) -> AccessPath: ... def _array_item_missing(self, _1: int, /) -> AccessPath: ... def _map_item_missing(self, _1: Any, /) -> AccessPath: ... def _is_prefix_of(self, _1: AccessPath, /) -> bool: ... def _to_steps(self, /) -> Sequence[AccessStep]: ... def _path_equal(self, _1: AccessPath, /) -> bool: ... # fmt: on # tvm-ffi-stubgen(end) ``` Import section ~~~~~~~~~~~~~~ ``` # tvm-ffi-stubgen(begin): import-section # fmt: off # isort: off from __future__ import annotations from ..registry import init_ffi_api as _FFI_INIT_FUNC from typing import TYPE_CHECKING if TYPE_CHECKING: from collections.abc import Mapping, Sequence from tvm_ffi import Device, Object, Tensor, dtype from tvm_ffi.testing import TestIntPair from typing import Any, Callable # isort: on # fmt: on # tvm-ffi-stubgen(end) ``` Auto-populates imports used by generated stubs. Export ~~~~~~ ``` # tvm-ffi-stubgen(begin): export/_ffi_api # fmt: off # isort: off from ._ffi_api import * # noqa: F403 from ._ffi_api import __all__ as _ffi_api__all__ if "__all__" not in globals(): __all__ = [] __all__.extend(_ffi_api__all__) # isort: on # fmt: on # tvm-ffi-stubgen(end) ``` Re-exports a generated submodule's __all__ into the parent. __all__ ~~~~~~~ ``` __all__ = [ # tvm-ffi-stubgen(begin): __all__ "LIB", "IntPair", "raise_error", # tvm-ffi-stubgen(end) ] ``` Populates __all__ with generated classes/functions and LIB (if present). Type map ~~~~~~~~ ``` # tvm-ffi-stubgen(ty-map): <type_key> -> <python_type> ``` Maps runtime type keys to Python types used in generation. Example: ``` # tvm-ffi-stubgen(ty-map): ffi.reflection.AccessStep -> ffi.access_path.AccessStep ``` Import object ~~~~~~~~~~~~~ ``` # tvm-ffi-stubgen(import-object): <from>; <type_checking_only>; <alias> ``` Injects a custom import into generated code, optionally TYPE_CHECKING-only. Example: ``` # tvm-ffi-stubgen(import-object): ffi.Object;False;_ffi_Object ``` Skip file ~~~~~~~~~ ``` # tvm-ffi-stubgen(skip-file) ``` Prevents stubgen from modifying the file. ``` Report URL: https://github.com/apache/tvm-ffi/actions/runs/20344138291 With regards, GitHub Actions via GitBox --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
