This is an automated email from the ASF dual-hosted git repository.

guanmingchiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/mahout.git


The following commit(s) were added to refs/heads/main by this push:
     new 8c1efe2fa Replace mypy with ty for static type checking (#1042)
8c1efe2fa is described below

commit 8c1efe2fa96fef5ab04b75ecfddc2ce2d5402a41
Author: Guan-Ming (Wesley) Chiu <[email protected]>
AuthorDate: Thu Feb 12 10:36:22 2026 +0800

    Replace mypy with ty for static type checking (#1042)
---
 .pre-commit-config.yaml                        | 11 +++++++----
 examples/quantum_teleportation.py              |  2 ++
 pyproject.toml                                 | 12 ++++++++++++
 qdp/qdp-python/qumat_qdp/__init__.py           |  6 +++---
 qdp/qdp-python/tests/test_dlpack_validation.py | 16 +++++-----------
 qumat/amazon_braket_backend.py                 |  2 +-
 qumat/qdp.py                                   |  6 +++---
 qumat/qiskit_backend.py                        |  2 +-
 testing/qdp/test_bindings.py                   | 10 ++++------
 testing/utils/amazon_braket_helpers.py         | 19 ++++++++++---------
 testing/utils/qiskit_helpers.py                |  2 +-
 testing/utils/qumat_helpers.py                 | 10 ++++++----
 uv.lock                                        | 26 ++++++++++++++++++++++++++
 13 files changed, 81 insertions(+), 43 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 9936df58d..56eafc0ba 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -23,11 +23,14 @@ repos:
         files: \.py$
 
   # Static type checking
-  - repo: https://github.com/pre-commit/mirrors-mypy
-    rev: v1.19.0
+  - repo: local
     hooks:
-      - id: mypy
-        args: ["--ignore-missing-imports"]
+      - id: ty
+        name: ty check
+        entry: uv run ty check .
+        language: system
+        pass_filenames: false
+        types: [python]
 
   # Check Apache license headers
   - repo: https://github.com/lucas-c/pre-commit-hooks
diff --git a/examples/quantum_teleportation.py 
b/examples/quantum_teleportation.py
index d87a038e4..60e26bb7b 100644
--- a/examples/quantum_teleportation.py
+++ b/examples/quantum_teleportation.py
@@ -45,6 +45,7 @@ quantum_computer.apply_cnot_gate(0, 1)
 quantum_computer.apply_hadamard_gate(0)
 
 # Measure qubits 0 and 1
+assert quantum_computer.circuit is not None
 quantum_computer.circuit.measure([0, 1], [0, 1])
 
 # Step 4: Communicate measurement results to the receiver
@@ -69,6 +70,7 @@ if received_measurement_results[0] == 1:
 # The state on qubit 2 now matches the original state on qubit 0
 
 # Step 6: Measure the received state (optional)
+assert receiver_quantum_computer.circuit is not None
 receiver_quantum_computer.circuit.measure(2, 2)
 
 # Execute the quantum circuits and get the measurement results
diff --git a/pyproject.toml b/pyproject.toml
index fbd98914c..9c342cde6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -53,6 +53,7 @@ qdp = ["qumat-qdp"]
 dev = [
     "pytest>=9.0.1",
     "ruff>=0.13.1",
+    "ty>=0.0.16",
     "pre-commit>=3.0.0",
     "maturin>=1.10.2",
     "patchelf>=0.17.2.4",
@@ -83,6 +84,17 @@ markers = [
     "slow: marks tests as slow running",
 ]
 
+[tool.ty.src]
+exclude = [
+    ".github/scripts/",
+    "qdp/qdp-python/benchmark/",
+]
+
+[tool.ty.analysis]
+# _qdp: compiled Rust extension (no type info for members)
+# api: benchmark module loaded via sys.path in tests
+allowed-unresolved-imports = ["_qdp", "_qdp.*", "api", "api.*"]
+
 [build-system]
 requires = ["hatchling"]
 build-backend = "hatchling.build"
diff --git a/qdp/qdp-python/qumat_qdp/__init__.py 
b/qdp/qdp-python/qumat_qdp/__init__.py
index 79d1cecdd..972864ce1 100644
--- a/qdp/qdp-python/qumat_qdp/__init__.py
+++ b/qdp/qdp-python/qumat_qdp/__init__.py
@@ -40,9 +40,9 @@ from qumat_qdp.api import (
 )
 from qumat_qdp.loader import QuantumDataLoader
 
-# Re-export Rust extension types
-QdpEngine = _qdp.QdpEngine
-QuantumTensor = _qdp.QuantumTensor
+# Re-export Rust extension types (getattr for compiled extension module)
+QdpEngine = getattr(_qdp, "QdpEngine")
+QuantumTensor = getattr(_qdp, "QuantumTensor")
 run_throughput_pipeline_py = getattr(_qdp, "run_throughput_pipeline_py", None)
 
 __all__ = [
diff --git a/qdp/qdp-python/tests/test_dlpack_validation.py 
b/qdp/qdp-python/tests/test_dlpack_validation.py
index ce45bdf92..9f624a606 100644
--- a/qdp/qdp-python/tests/test_dlpack_validation.py
+++ b/qdp/qdp-python/tests/test_dlpack_validation.py
@@ -18,23 +18,17 @@
 
 import pytest
 
-try:
-    import torch
-    from _qdp import QdpEngine
-except ImportError:
-    torch = None
-    QdpEngine = None
+torch = pytest.importorskip("torch")
+_qdp = pytest.importorskip("_qdp")
+QdpEngine = _qdp.QdpEngine
 
 
 def _cuda_available():
-    return torch is not None and torch.cuda.is_available()
+    return torch.cuda.is_available()
 
 
 def _engine():
-    if QdpEngine is None:
-        pytest.skip("_qdp not built")
-    e = QdpEngine(0)
-    return e
+    return QdpEngine(0)
 
 
 @pytest.mark.skipif(not _cuda_available(), reason="CUDA not available")
diff --git a/qumat/amazon_braket_backend.py b/qumat/amazon_braket_backend.py
index 6b4061a7b..57a086fb6 100644
--- a/qumat/amazon_braket_backend.py
+++ b/qumat/amazon_braket_backend.py
@@ -52,7 +52,7 @@ def create_empty_circuit(num_qubits: int | None = None):
     circuit = Circuit()
     if num_qubits is not None:
         for i in range(num_qubits):
-            circuit.i(i)
+            circuit.i(i)  # type: ignore[unresolved-attribute]
     return circuit
 
 
diff --git a/qumat/qdp.py b/qumat/qdp.py
index ae4536c19..d62a0946f 100644
--- a/qumat/qdp.py
+++ b/qumat/qdp.py
@@ -38,7 +38,7 @@ _INSTALL_MSG = (
 def _make_stub(name: str) -> type:
     """Create a stub class that raises ImportError on instantiation."""
 
-    def __init__(self, *args, **kwargs):  # type: ignore[no-untyped-def]
+    def __init__(self, *args, **kwargs):
         raise ImportError(_INSTALL_MSG)
 
     return type(name, (), {"__init__": __init__, "__doc__": f"Stub class - 
{name}"})
@@ -57,7 +57,7 @@ except ImportError as e:
         ImportWarning,
     )
 
-    QdpEngine = _make_stub("QdpEngine")  # type: ignore[misc]
-    QuantumTensor = _make_stub("QuantumTensor")  # type: ignore[misc]
+    QdpEngine = _make_stub("QdpEngine")
+    QuantumTensor = _make_stub("QuantumTensor")
 
 __all__ = ["QdpEngine", "QuantumTensor"]
diff --git a/qumat/qiskit_backend.py b/qumat/qiskit_backend.py
index 88acaf9a5..db61d1977 100644
--- a/qumat/qiskit_backend.py
+++ b/qumat/qiskit_backend.py
@@ -36,7 +36,7 @@ def initialize_backend(backend_config):
     else:
         backend = AerSimulator(method=simulator_type)
 
-    backend.shots = shots
+    backend.shots = shots  # type: ignore[unresolved-attribute]  # 
runtime-settable
     return backend
 
 
diff --git a/testing/qdp/test_bindings.py b/testing/qdp/test_bindings.py
index 007def16e..73a553bd4 100644
--- a/testing/qdp/test_bindings.py
+++ b/testing/qdp/test_bindings.py
@@ -939,8 +939,8 @@ def test_iqp_encode_3_qubits():
     assert torch_tensor.shape == (1, 8)
 
     # Should get |000⟩ state: amplitude 1 at index 0, 0 elsewhere
-    expected = torch.zeros((1, 8), dtype=torch.complex128, device="cuda:0")
-    expected[0, 0] = 1.0 + 0j
+    row = [1.0 + 0j] + [0.0 + 0j] * 7
+    expected = torch.tensor([row], dtype=torch.complex128, device="cuda:0")
     assert torch.allclose(torch_tensor, expected, atol=1e-6)
 
 
@@ -1143,10 +1143,8 @@ def test_iqp_fwt_zero_params_gives_zero_state():
 
         # Should get |0...0⟩: amplitude 1 at index 0, 0 elsewhere
         state_len = 1 << num_qubits
-        expected = torch.zeros(
-            (1, state_len), dtype=torch_tensor.dtype, device="cuda:0"
-        )
-        expected[0, 0] = 1.0 + 0j
+        row = [1.0 + 0j] + [0.0 + 0j] * (state_len - 1)
+        expected = torch.tensor([row], dtype=torch_tensor.dtype, 
device="cuda:0")
 
         assert torch.allclose(torch_tensor, expected, atol=1e-6), (
             f"IQP {num_qubits} qubits with zero params should give |0⟩ state"
diff --git a/testing/utils/amazon_braket_helpers.py 
b/testing/utils/amazon_braket_helpers.py
index 06f43296c..e8a04bbb2 100644
--- a/testing/utils/amazon_braket_helpers.py
+++ b/testing/utils/amazon_braket_helpers.py
@@ -43,32 +43,33 @@ def get_native_example_final_state_vector(
     # Use LocalSimulator for state vector simulation
     device = LocalSimulator()
 
+    # Braket Circuit gate methods (.h, .x, .cnot, etc.) are generated via 
__getattr__
     circuit = Circuit()
 
     # Initialize to desired state
     for i, bit in enumerate(initial_state_ket_str):
         if bit == "1":
-            circuit.x(i)
+            circuit.x(i)  # type: ignore[unresolved-attribute]
 
     # Create entanglement between qubits 1 and 2
-    circuit.h(1)
-    circuit.cnot(1, 2)
+    circuit.h(1)  # type: ignore[unresolved-attribute]
+    circuit.cnot(1, 2)  # type: ignore[unresolved-attribute]
 
     # Prepare the state to be teleported on qubit 0
-    circuit.h(0)
-    circuit.z(0)
+    circuit.h(0)  # type: ignore[unresolved-attribute]
+    circuit.z(0)  # type: ignore[unresolved-attribute]
 
     # Perform Bell measurement on qubits 0 and 1
-    circuit.cnot(0, 1)
-    circuit.h(0)
+    circuit.cnot(0, 1)  # type: ignore[unresolved-attribute]
+    circuit.h(0)  # type: ignore[unresolved-attribute]
 
     # Add state_vector result type to get the final state
-    circuit.state_vector()
+    circuit.state_vector()  # type: ignore[unresolved-attribute]
 
     # Run the circuit
     result = device.run(circuit, shots=0).result()
 
     # Get the state vector (values is a complex numpy array)
-    state_vector = result.values[0]
+    state_vector = result.values[0]  # type: ignore[possibly-missing-attribute]
 
     return state_vector
diff --git a/testing/utils/qiskit_helpers.py b/testing/utils/qiskit_helpers.py
index 045a336cd..37a09d2f5 100644
--- a/testing/utils/qiskit_helpers.py
+++ b/testing/utils/qiskit_helpers.py
@@ -64,7 +64,7 @@ def get_native_example_final_state_vector(
     qc.h(0)  # Apply Hadamard gate on qubit 0
 
     # Add save_statevector instruction
-    qc.save_statevector()
+    qc.save_statevector()  # type: ignore[unresolved-attribute]  # qiskit-aer 
extension
 
     # Simulate the circuit
     transpiled_qc = transpile(qc, simulator)
diff --git a/testing/utils/qumat_helpers.py b/testing/utils/qumat_helpers.py
index d97311bc4..d0dcdd023 100644
--- a/testing/utils/qumat_helpers.py
+++ b/testing/utils/qumat_helpers.py
@@ -57,20 +57,22 @@ class BinaryString(str):
 
 def create_np_computational_basis_state(
     ket_str: BinaryString, np_dtype: str = "complex128"
-) -> np.array:
+) -> np.ndarray:
     single_qubit_state_dict = {
         "0": np.array([1, 0], dtype=np_dtype),
         "1": np.array([0, 1], dtype=np_dtype),
     }
 
-    single_qubit_vectors = map(single_qubit_state_dict.get, ket_str)
-    computational_basis_vector = reduce(np.kron, single_qubit_vectors)
+    single_qubit_vectors = [single_qubit_state_dict[c] for c in ket_str]
+    computational_basis_vector = reduce(
+        lambda a, b: np.kron(a, b), single_qubit_vectors
+    )
 
     return computational_basis_vector
 
 
 def get_qumat_example_final_state_vector(
-    backend_config: dict, initial_state_ket_str: BinaryString = 
BinaryString("000")
+    backend_config: dict, initial_state_ket_str: str = "000"
 ):
     n_qubits = len(initial_state_ket_str)
     assert n_qubits == 3, print(
diff --git a/uv.lock b/uv.lock
index 9a2f34c99..58305bc7a 100644
--- a/uv.lock
+++ b/uv.lock
@@ -1947,6 +1947,7 @@ dev = [
     { name = "setuptools" },
     { name = "tensorflow" },
     { name = "torch" },
+    { name = "ty" },
 ]
 
 [package.metadata]
@@ -1971,6 +1972,7 @@ dev = [
     { name = "setuptools", specifier = ">=80.9.0" },
     { name = "tensorflow", specifier = ">=2.20" },
     { name = "torch", specifier = ">=2.2,<=2.9.0" },
+    { name = "ty", specifier = ">=0.0.16" },
 ]
 
 [[package]]
@@ -2402,6 +2404,30 @@ wheels = [
     { url = 
"https://files.pythonhosted.org/packages/f5/3a/e991574f3102147b642e49637e0281e9bb7c4ba254edb2bab78247c85e01/triton-3.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl";,
 hash = 
"sha256:c9e71db82261c4ffa3921cd050cd5faa18322d2d405c30eb56084afaff3b0833", size 
= 170476535, upload-time = "2025-10-13T16:38:05.18Z" },
 ]
 
+[[package]]
+name = "ty"
+version = "0.0.16"
+source = { registry = "https://pypi.org/simple"; }
+sdist = { url = 
"https://files.pythonhosted.org/packages/ee/18/77f84d89db54ea0d1d1b09fa2f630ac4c240c8e270761cb908c06b6e735c/ty-0.0.16.tar.gz";,
 hash = 
"sha256:a999b0db6aed7d6294d036ebe43301105681e0c821a19989be7c145805d7351c", size 
= 5129637, upload-time = "2026-02-10T20:24:16.48Z" }
+wheels = [
+    { url = 
"https://files.pythonhosted.org/packages/67/b9/909ebcc7f59eaf8a2c18fb54bfcf1c106f99afb3e5460058d4b46dec7b20/ty-0.0.16-py3-none-linux_armv6l.whl";,
 hash = 
"sha256:6d8833b86396ed742f2b34028f51c0e98dbf010b13ae4b79d1126749dc9dab15", size 
= 10113870, upload-time = "2026-02-10T20:24:11.864Z" },
+    { url = 
"https://files.pythonhosted.org/packages/c3/2c/b963204f3df2fdbf46a4a1ea4a060af9bb676e065d59c70ad0f5ae0dbae8/ty-0.0.16-py3-none-macosx_10_12_x86_64.whl";,
 hash = 
"sha256:934c0055d3b7f1cf3c8eab78c6c127ef7f347ff00443cef69614bda6f1502377", size 
= 9936286, upload-time = "2026-02-10T20:24:08.695Z" },
+    { url = 
"https://files.pythonhosted.org/packages/ef/4d/3d78294f2ddfdded231e94453dea0e0adef212b2bd6536296039164c2a3e/ty-0.0.16-py3-none-macosx_11_0_arm64.whl";,
 hash = 
"sha256:b55e8e8733b416d914003cd22e831e139f034681b05afed7e951cc1a5ea1b8d4", size 
= 9442660, upload-time = "2026-02-10T20:24:02.704Z" },
+    { url = 
"https://files.pythonhosted.org/packages/15/40/ce48c0541e3b5749b0890725870769904e6b043e077d4710e5325d5cf807/ty-0.0.16-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl";,
 hash = 
"sha256:feccae8f4abd6657de111353bd604f36e164844466346eb81ffee2c2b06ea0f0", size 
= 9934506, upload-time = "2026-02-10T20:24:35.818Z" },
+    { url = 
"https://files.pythonhosted.org/packages/84/16/3b29de57e1ec6e56f50a4bb625ee0923edb058c5f53e29014873573a00cd/ty-0.0.16-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl";,
 hash = 
"sha256:1cad5e29d8765b92db5fa284940ac57149561f3f89470b363b9aab8a6ce553b0", size 
= 9933099, upload-time = "2026-02-10T20:24:43.003Z" },
+    { url = 
"https://files.pythonhosted.org/packages/f7/a1/e546995c25563d318c502b2f42af0fdbed91e1fc343708241e2076373644/ty-0.0.16-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl";,
 hash = 
"sha256:86f28797c7dc06f081238270b533bf4fc8e93852f34df49fb660e0b58a5cda9a", size 
= 10438370, upload-time = "2026-02-10T20:24:33.44Z" },
+    { url = 
"https://files.pythonhosted.org/packages/11/c1/22d301a4b2cce0f75ae84d07a495f87da193bcb68e096d43695a815c4708/ty-0.0.16-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl";,
 hash = 
"sha256:be971a3b42bcae44d0e5787f88156ed2102ad07558c05a5ae4bfd32a99118e66", size 
= 10992160, upload-time = "2026-02-10T20:24:25.574Z" },
+    { url = 
"https://files.pythonhosted.org/packages/6f/40/f1892b8c890db3f39a1bab8ec459b572de2df49e76d3cad2a9a239adcde9/ty-0.0.16-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl";,
 hash = 
"sha256:3c9f982b7c4250eb91af66933f436b3a2363c24b6353e94992eab6551166c8b7", size 
= 10717892, upload-time = "2026-02-10T20:24:05.914Z" },
+    { url = 
"https://files.pythonhosted.org/packages/2f/1b/caf9be8d0c738983845f503f2e92ea64b8d5fae1dd5ca98c3fca4aa7dadc/ty-0.0.16-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl";,
 hash = 
"sha256:d122edf85ce7bdf6f85d19158c991d858fc835677bd31ca46319c4913043dc84", size 
= 10510916, upload-time = "2026-02-10T20:24:00.252Z" },
+    { url = 
"https://files.pythonhosted.org/packages/60/ea/28980f5c7e1f4c9c44995811ea6a36f2fcb205232a6ae0f5b60b11504621/ty-0.0.16-py3-none-musllinux_1_2_aarch64.whl";,
 hash = 
"sha256:497ebdddbb0e35c7758ded5aa4c6245e8696a69d531d5c9b0c1a28a075374241", size 
= 9908506, upload-time = "2026-02-10T20:24:28.133Z" },
+    { url = 
"https://files.pythonhosted.org/packages/f7/80/8672306596349463c21644554f935ff8720679a14fd658fef658f66da944/ty-0.0.16-py3-none-musllinux_1_2_armv7l.whl";,
 hash = 
"sha256:e1e0ac0837bde634b030243aeba8499383c0487e08f22e80f5abdacb5b0bd8ce", size 
= 9949486, upload-time = "2026-02-10T20:24:18.62Z" },
+    { url = 
"https://files.pythonhosted.org/packages/8b/8a/d8747d36f30bd82ea157835f5b70d084c9bb5d52dd9491dba8a149792d6a/ty-0.0.16-py3-none-musllinux_1_2_i686.whl";,
 hash = 
"sha256:1216c9bcca551d9f89f47a817ebc80e88ac37683d71504e5509a6445f24fd024", size 
= 10145269, upload-time = "2026-02-10T20:24:38.249Z" },
+    { url = 
"https://files.pythonhosted.org/packages/6f/4c/753535acc7243570c259158b7df67e9c9dd7dab9a21ee110baa4cdcec45d/ty-0.0.16-py3-none-musllinux_1_2_x86_64.whl";,
 hash = 
"sha256:221bbdd2c6ee558452c96916ab67fcc465b86967cf0482e19571d18f9c831828", size 
= 10608644, upload-time = "2026-02-10T20:24:40.565Z" },
+    { url = 
"https://files.pythonhosted.org/packages/3e/05/8e8db64cf45a8b16757e907f7a3bfde8d6203e4769b11b64e28d5bdcd79a/ty-0.0.16-py3-none-win32.whl";,
 hash = 
"sha256:d52c4eb786be878e7514cab637200af607216fcc5539a06d26573ea496b26512", size 
= 9582579, upload-time = "2026-02-10T20:24:30.406Z" },
+    { url = 
"https://files.pythonhosted.org/packages/25/bc/45759faea132cd1b2a9ff8374e42ba03d39d076594fbb94f3e0e2c226c62/ty-0.0.16-py3-none-win_amd64.whl";,
 hash = 
"sha256:f572c216aa8ecf79e86589c6e6d4bebc01f1f3cb3be765c0febd942013e1e73a", size 
= 10436043, upload-time = "2026-02-10T20:23:57.51Z" },
+    { url = 
"https://files.pythonhosted.org/packages/7f/02/70a491802e7593e444137ed4e41a04c34d186eb2856f452dd76b60f2e325/ty-0.0.16-py3-none-win_arm64.whl";,
 hash = 
"sha256:430eadeb1c0de0c31ef7bef9d002bdbb5f25a31e3aad546f1714d76cd8da0a87", size 
= 9915122, upload-time = "2026-02-10T20:24:14.285Z" },
+]
+
 [[package]]
 name = "typedunits"
 version = "0.0.1"

Reply via email to