This is an automated email from the ASF dual-hosted git repository.
junrushao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git
The following commit(s) were added to refs/heads/main by this push:
new d2e9aa6 chore(build): Distribute manylinux2014 wheels (#146)
d2e9aa6 is described below
commit d2e9aa678b53a67d9e0e757992191b95f9a726e1
Author: Junru Shao <[email protected]>
AuthorDate: Thu Oct 16 10:17:15 2025 -0700
chore(build): Distribute manylinux2014 wheels (#146)
Originally we are releasing manylinux2_28 as the default setting of
cibuildwheel. However, realistically there are old systems that are not
equipped with adequate glibc version. Switch to manylinux2014 is fine to
TVM FFI so we are doing it in this PR
---
.github/workflows/ci_test.yml | 4 ++--
pyproject.toml | 4 +++-
python/tvm_ffi/base.py | 4 +++-
python/tvm_ffi/container.py | 32 ++++++++++++++++++++++++--------
python/tvm_ffi/dataclasses/_utils.py | 8 ++++----
python/tvm_ffi/dataclasses/c_class.py | 14 +++++++++-----
tests/python/test_container.py | 10 +++++++++-
tests/python/test_dtype.py | 3 ++-
8 files changed, 56 insertions(+), 23 deletions(-)
diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml
index 0fa1554..b463682 100644
--- a/.github/workflows/ci_test.yml
+++ b/.github/workflows/ci_test.yml
@@ -80,8 +80,8 @@ jobs:
matrix:
include:
- {os: ubuntu-latest, arch: x86_64, python_version: '3.14t'}
- - {os: ubuntu-24.04-arm, arch: aarch64, python_version: '3.10'}
- - {os: windows-latest, arch: AMD64, python_version: '3.12'}
+ - {os: ubuntu-24.04-arm, arch: aarch64, python_version: '3.8'}
+ - {os: windows-latest, arch: AMD64, python_version: '3.9'}
- {os: macos-14, arch: arm64, python_version: '3.13'}
steps:
diff --git a/pyproject.toml b/pyproject.toml
index 83a87a4..0800264 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -221,6 +221,8 @@ docstring-code-line-length = "dynamic"
[tool.cibuildwheel]
build-verbosity = 1
+manylinux-x86_64-image = "manylinux2014"
+manylinux-aarch64-image = "manylinux2014"
# only build up to cp312, cp312
# will be abi3 and can be used in future versions
@@ -245,7 +247,7 @@ environment = { MACOSX_DEPLOYMENT_TARGET = "10.14" }
archs = ["AMD64"]
[tool.mypy]
-python_version = "3.8"
+python_version = "3.9"
show_error_codes = true
mypy_path = ["python", "examples", "tests/python"]
files = ["python/tvm_ffi", "examples", "tests/python"]
diff --git a/python/tvm_ffi/base.py b/python/tvm_ffi/base.py
index 3a3eede..45c9be2 100644
--- a/python/tvm_ffi/base.py
+++ b/python/tvm_ffi/base.py
@@ -29,7 +29,9 @@ logger = logging.getLogger(__name__)
# ----------------------------
# Python3 version.
# ----------------------------
-if not (sys.version_info[0] >= 3 and sys.version_info[1] >= 8):
+if sys.version_info[:2] < (3, 8): # noqa: UP036
+ # Disables ruff(UP036): Version block is outdated for minimum Python
version
+ # This is to ensure that the error message is sufficiently user friendly
PY3STATEMENT = "The minimal Python requirement is Python 3.8"
raise Exception(PY3STATEMENT)
diff --git a/python/tvm_ffi/container.py b/python/tvm_ffi/container.py
index 046f8c9..a23fa47 100644
--- a/python/tvm_ffi/container.py
+++ b/python/tvm_ffi/container.py
@@ -21,10 +21,6 @@ from __future__ import annotations
import itertools
import operator
import sys
-from collections.abc import ItemsView as ItemsViewBase
-from collections.abc import Iterable, Iterator, Mapping, Sequence
-from collections.abc import KeysView as KeysViewBase
-from collections.abc import ValuesView as ValuesViewBase
from typing import (
Any,
Callable,
@@ -37,18 +33,38 @@ from typing import (
from . import _ffi_api, core
from .registry import register_object
-# workarounds for python 3.8
-if not (sys.version_info[0] == 3 and sys.version_info[1] <= 8):
- from typing import (
+if sys.version_info >= (3, 9):
+ # PEP 585 generics
+ from collections.abc import (
ItemsView as ItemsViewBase,
)
- from typing import (
+ from collections.abc import (
+ Iterable,
+ Iterator,
+ Mapping,
+ Sequence,
+ )
+ from collections.abc import (
KeysView as KeysViewBase,
)
+ from collections.abc import (
+ ValuesView as ValuesViewBase,
+ )
+else: # Python 3.8
+ # workarounds for python 3.8
+ # typing-module generics (subscriptable on 3.8)
from typing import (
+ ItemsView as ItemsViewBase,
+ )
+ from typing import (
+ Iterable,
+ Iterator,
Mapping,
Sequence,
)
+ from typing import (
+ KeysView as KeysViewBase,
+ )
from typing import (
ValuesView as ValuesViewBase,
)
diff --git a/python/tvm_ffi/dataclasses/_utils.py
b/python/tvm_ffi/dataclasses/_utils.py
index 60f31fb..bd647a6 100644
--- a/python/tvm_ffi/dataclasses/_utils.py
+++ b/python/tvm_ffi/dataclasses/_utils.py
@@ -20,7 +20,7 @@ from __future__ import annotations
import functools
from dataclasses import MISSING
-from typing import Any, Callable, TypeVar, cast
+from typing import Any, Callable, Type, TypeVar, cast
from ..core import (
Object,
@@ -33,9 +33,9 @@ _InputClsType = TypeVar("_InputClsType")
def type_info_to_cls(
type_info: TypeInfo,
- cls: type[_InputClsType],
+ cls: Type[_InputClsType], # noqa: UP006
methods: dict[str, Callable[..., Any] | None],
-) -> type[_InputClsType]:
+) -> Type[_InputClsType]: # noqa: UP006
assert type_info.type_cls is None, "Type class is already created"
# Step 1. Determine the base classes
cls_bases = cls.__bases__
@@ -77,7 +77,7 @@ def type_info_to_cls(
new_cls = type(cls.__name__, cls_bases, attrs)
new_cls.__module__ = cls.__module__
new_cls = functools.wraps(cls, updated=())(new_cls) # type: ignore
- return cast(type[_InputClsType], new_cls)
+ return cast(Type[_InputClsType], new_cls)
def fill_dataclass_field(type_cls: type, type_field: TypeField) -> None:
diff --git a/python/tvm_ffi/dataclasses/c_class.py
b/python/tvm_ffi/dataclasses/c_class.py
index 0a09740..0bc273c 100644
--- a/python/tvm_ffi/dataclasses/c_class.py
+++ b/python/tvm_ffi/dataclasses/c_class.py
@@ -25,9 +25,10 @@ method is synthesized to call the FFI constructor when
requested.
from __future__ import annotations
+import sys
from collections.abc import Callable
from dataclasses import InitVar
-from typing import ClassVar, TypeVar, get_origin, get_type_hints
+from typing import ClassVar, Type, TypeVar, get_origin, get_type_hints
from typing_extensions import dataclass_transform
@@ -41,7 +42,7 @@ _InputClsType = TypeVar("_InputClsType")
@dataclass_transform(field_specifiers=(field,))
def c_class(
type_key: str, init: bool = True
-) -> Callable[[type[_InputClsType]], type[_InputClsType]]:
+) -> Callable[[Type[_InputClsType]], Type[_InputClsType]]: # noqa: UP006
"""(Experimental) Create a dataclass-like proxy for a C++ class registered
with TVM FFI.
The decorator reads the reflection metadata that was registered on the C++
@@ -114,7 +115,7 @@ def c_class(
"""
- def decorator(super_type_cls: type[_InputClsType]) -> type[_InputClsType]:
+ def decorator(super_type_cls: Type[_InputClsType]) -> Type[_InputClsType]:
# noqa: UP006
nonlocal init
init = init and "__init__" not in super_type_cls.__dict__
# Step 1. Retrieve `type_info` from registry
@@ -126,7 +127,7 @@ def c_class(
_utils.fill_dataclass_field(super_type_cls, type_field)
# Step 3. Create the proxy class with the fields as properties
fn_init = _utils.method_init(super_type_cls, type_info) if init else
None
- type_cls: type[_InputClsType] = _utils.type_info_to_cls(
+ type_cls: Type[_InputClsType] = _utils.type_info_to_cls( # noqa: UP006
type_info=type_info,
cls=super_type_cls,
methods={"__init__": fn_init},
@@ -138,7 +139,10 @@ def c_class(
def _inspect_c_class_fields(type_cls: type, type_info: TypeInfo) ->
list[TypeField]:
- type_hints_resolved = get_type_hints(type_cls, include_extras=True)
+ if sys.version_info >= (3, 9):
+ type_hints_resolved = get_type_hints(type_cls, include_extras=True)
+ else:
+ type_hints_resolved = get_type_hints(type_cls)
type_hints_py = {
name: type_hints_resolved[name]
for name in getattr(type_cls, "__annotations__", {}).keys()
diff --git a/tests/python/test_container.py b/tests/python/test_container.py
index 3f3465e..e15f00b 100644
--- a/tests/python/test_container.py
+++ b/tests/python/test_container.py
@@ -15,12 +15,20 @@
# specific language governing permissions and limitations
# under the License.
import pickle
-from collections.abc import Sequence
+import sys
from typing import Any
import pytest
import tvm_ffi
+if sys.version_info >= (3, 9):
+ # PEP 585 generics
+ from collections.abc import Sequence
+else: # Python 3.8
+ # workarounds for python 3.8
+ # typing-module generics (subscriptable on 3.8)
+ from typing import Sequence
+
def test_array() -> None:
a = tvm_ffi.convert([1, 2, 3])
diff --git a/tests/python/test_dtype.py b/tests/python/test_dtype.py
index 6c45416..38e72fb 100644
--- a/tests/python/test_dtype.py
+++ b/tests/python/test_dtype.py
@@ -122,7 +122,8 @@ def test_torch_dtype_conversion() -> None:
_check_dtype(torch.float8_e4m3fnuz, 11, 8, 1)
_check_dtype(torch.float8_e5m2, 12, 8, 1)
_check_dtype(torch.float8_e5m2fnuz, 13, 8, 1)
- _check_dtype(torch.float8_e8m0fnu, 14, 8, 1)
+ if hasattr(torch, "float8_e8m0fnu"):
+ _check_dtype(torch.float8_e8m0fnu, 14, 8, 1)
def test_numpy_dtype_conversion() -> None: