From e3c94afe4a0ec5a61c0504ad8f0bac5dfc83877c Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Wed, 14 Oct 2026 14:29:15 +0000 Subject: [PATCH 1/2] topk-sdk: Add version 0.15.0 --- .github/workflows/build-topk-sdk.yml | 128 +++++++++++++++++++++++++++ docs/packages/topk-sdk.yaml | 5 ++ 2 files changed, 133 insertions(+) create mode 100644 .github/workflows/build-topk-sdk.yml create mode 100644 docs/packages/topk-sdk.yaml diff --git a/.github/workflows/build-topk-sdk.yml b/.github/workflows/build-topk-sdk.yml new file mode 100644 index 000000000000..e2da1e5eeeb4 --- /dev/null +++ b/.github/workflows/build-topk-sdk.yml @@ -0,0 +1,128 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on the `linux` job of +# https://github.com/topk-io/topk/blob/0.15.0/.github/workflows/publish_python.yml +name: Build topk-sdk wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/topk-sdk.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-topk-sdk.yml' + - 'docs/packages/topk-sdk.yaml' + push: + branches: [main] + paths: + - '.github/workflows/build-topk-sdk.yml' + - 'docs/packages/topk-sdk.yaml' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: topk-sdk + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build topk-sdk ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 240 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + # No cp314t: upstream ships cp39-cp314 only, all cp3x-cp3x, and the + # module does not declare `gil_used(false)`. + python: ["cp312", "cp313", "cp314"] + + env: + TOPK_SDK_VERSION: ${{ matrix.version }} + + steps: + # topk-py builds against the sibling topk-rs crate and ../protos, so the + # whole monorepo is checked out. + - name: Checkout topk ${{ env.TOPK_SDK_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: topk-io/topk + ref: ${{ env.TOPK_SDK_VERSION }} + persist-credentials: false + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + package-dir: topk-py + output-dir: wheelhouse/ + # musllinux is dropped: rustup.rs ships no riscv64 musl toolchain. + only: ${{ matrix.python }}-manylinux_riscv64 + env: + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # protobuf ships no riscv64 protoc release; Rocky 10's CRB repo + # (enabled in the manylinux image) has one. + CIBW_BEFORE_ALL_LINUX: >- + yum install -y protobuf-compiler && + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | + sh -s -- -y --profile minimal + CIBW_ENVIRONMENT_LINUX: >- + PATH="$PATH:$HOME/.cargo/bin" + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + CIBW_TEST_ENVIRONMENT_LINUX: PIP_ONLY_BINARY=numpy + CIBW_TEST_REQUIRES: pytest pytest-asyncio + # test-sources resolves against the checkout root, not package-dir. + CIBW_TEST_SOURCES: topk-py/tests + # The rest of upstream's suite needs TOPK_API_KEY and a live topk + # sandbox; these files exercise the extension offline. + CIBW_TEST_COMMAND: >- + python -c "import topk_sdk.topk_sdk as m; + assert m.__file__.endswith('.so'), m.__file__" && + python -m pytest -v + topk-py/tests/test_data_bytes.py + topk-py/tests/test_data_list.py + topk-py/tests/test_data_matrix.py + topk-py/tests/test_data_struct.py + topk-py/tests/test_data_vector_dense.py + topk-py/tests/test_data_vector_sparse.py + topk-py/tests/test_query_expr.py + topk-py/tests/test_retry_config.py + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: topk-sdk-${{ env.TOPK_SDK_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish topk-sdk ${{ matrix.version }} + needs: [setup, build_wheels] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + secrets: + app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} + with: + artifact-pattern: topk-sdk-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/docs/packages/topk-sdk.yaml b/docs/packages/topk-sdk.yaml new file mode 100644 index 000000000000..9444d488948a --- /dev/null +++ b/docs/packages/topk-sdk.yaml @@ -0,0 +1,5 @@ +package-name: topk-sdk +source-code: https://github.com/topk-io/topk +license: MIT +versions: +- version: 0.15.0 From f7918b154d9b86316aba6b75eb86f0fcb2224679 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Thu, 15 Oct 2026 10:03:32 +0000 Subject: [PATCH 2/2] topk-sdk: accept either TryFromIntError wording in overflow tests Build topk-sdk 0.15.0 cp314-manylinux_riscv64 failed 3 of its offline tests (TestU8Vector/TestI8Vector/TestBinaryVector::test_invalid_ number_range): each expects OverflowError matching "out of range integral type conversion attempted", but got "number too large/small to fit in target type" instead -- same exception, different libstd wording. pyo3's own FromPyObject/ impls raise this by wrapping std::num::TryFromIntError's Display text verbatim, and topk-py's Cargo.toml pins no Cargo.lock of its own, so this build's actual Rust toolchain renders the newer libstd message. Not riscv64-specific -- reproduces on any architecture with the same toolchain. Widens the test's expected regex to accept either wording. --- .github/workflows/build-topk-sdk.yml | 9 ++++ ...01-accept-current-tryfromint-wording.patch | 47 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 patches/topk-sdk/0.15.0/0001-accept-current-tryfromint-wording.patch diff --git a/.github/workflows/build-topk-sdk.yml b/.github/workflows/build-topk-sdk.yml index e2da1e5eeeb4..ea955cc90716 100644 --- a/.github/workflows/build-topk-sdk.yml +++ b/.github/workflows/build-topk-sdk.yml @@ -67,6 +67,15 @@ jobs: ref: ${{ env.TOPK_SDK_VERSION }} persist-credentials: false + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + persist-credentials: false + + - name: Apply patches + run: git apply python-wheels/patches/topk-sdk/${{ env.TOPK_SDK_VERSION }}/*.patch + - name: Build wheels uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 with: diff --git a/patches/topk-sdk/0.15.0/0001-accept-current-tryfromint-wording.patch b/patches/topk-sdk/0.15.0/0001-accept-current-tryfromint-wording.patch new file mode 100644 index 000000000000..75a22e8247ea --- /dev/null +++ b/patches/topk-sdk/0.15.0/0001-accept-current-tryfromint-wording.patch @@ -0,0 +1,47 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Wed, 15 Oct 2026 00:00:02 +0000 +Subject: [PATCH] tests: accept the current Rust stdlib TryFromIntError wording too + +Upstream-Status: To upstream [test asserts the Rust stdlib's old TryFromIntError message; a newer toolchain already renders it differently, reproduces on any architecture] + +test_invalid_number_range in TestU8Vector/TestI8Vector/TestBinaryVector +expects pytest.raises(OverflowError, match=TYPE_ERROR_OUT_OF_RANGE) +with TYPE_ERROR_OUT_OF_RANGE = "out of range integral type conversion +attempted", but this build's CI actually raises OverflowError with +"number too large to fit in target type" / "number too small to fit +in target type" instead -- same exception type, different wording. + +u8/i8 vector arguments are extracted via pyo3's own built-in +FromPyObject/FromPyObject impls, which convert an out-of-range +Python int by calling u8::try_from(val)/i8::try_from(val) and wrapping +the resulting std::num::TryFromIntError's Display text +(`e.to_string()`) in a PyOverflowError (confirmed directly in pyo3 +0.27.0's own source, src/conversions/std/num.rs) -- so the exact +wording is the Rust standard library's TryFromIntError message, not +anything topk-py's own code controls. The two wordings above are two +different TryFromIntError messages a std library can render (the +exact phrasing has changed across Rust releases); topk-py's Cargo.toml +pins no Cargo.lock for its own crate, so a fresh build on any platform +picks up whatever Rust toolchain the runner carries, and this build's +toolchain renders the newer wording. Not riscv64-specific -- libstd's +error text is architecture-independent, so an x86_64 build with the +same toolchain would hit the identical mismatch. Widens the regex to +accept either wording rather than forcing a narrower toolchain pin +just for this. + +Signed-off-by: Ludovic Henry +--- +diff --git a/topk-py/tests/test_data_vector_dense.py b/topk-py/tests/test_data_vector_dense.py +index 927c4b3..9334f93 100644 +--- a/topk-py/tests/test_data_vector_dense.py ++++ b/topk-py/tests/test_data_vector_dense.py +@@ -3,7 +3,7 @@ from topk_sdk.data import binary_vector, f8_vector, f16_vector, f32_vector, u8_v + + TYPE_ERROR = "Invalid vector value" + TYPE_ERROR_INT_TO_VECTOR = "argument 'vector': 'int' object cannot be cast as 'Sequence'" +-TYPE_ERROR_OUT_OF_RANGE = "out of range integral type conversion attempted" ++TYPE_ERROR_OUT_OF_RANGE = "(out of range integral type conversion attempted|number too (?:large|small) to fit in target type)" + TYPE_ERROR_NONE_TO_VECTOR = "argument 'vector': 'NoneType' object cannot be cast as 'Sequence'" + TYPE_ERROR_BOOL_TO_VECTOR = "argument 'vector': 'bool' object cannot be cast as 'Sequence'" + TYPE_ERROR_FLOAT_TO_VECTOR = "argument 'vector': 'float' object cannot be cast as 'Sequence'"