Skip to content

[Compatibility Issue] Missing numpy>=2 constraint — np.typing may crash on numpy<2 #160

Description

@xyf5432

Affected File

core/predict.py:154,198

Current Code

# core/predict.py
import numpy as np
import torch
# ... (no import numpy.typing, no from __future__ import annotations)

def get_prediction(self, left_counts: np.typing.ArrayLike, right_counts: np.typing.ArrayLike):  # L154
    ...

def get_prediction_with_terrain(self, full_features: np.typing.ArrayLike):  # L198
    ...

No from __future__ import annotations — annotations are evaluated at definition time.

Root Cause

numpy.typing is only accessible as a module attribute (np.typing.XXX) in numpy >= 2.0.0 (via __getattr__). On numpy < 2.0, access without a prior import numpy.typing triggers:

AttributeError: module 'numpy' has no attribute 'typing'

The issue arises because numpy.typing becomes available on numpy<2 only if some earlier code in the import chain has executed import numpy.typing — once imported, it is injected into numpy.__dict__.

Dependency

pyproject.toml declares "numpy" and "pandas" with no version constraints:

dependencies = [
    "numpy",        # no version constraint
    "pandas",       # no version constraint
    "matplotlib",
    "onnxruntime",
    ...
]

This allows pip to resolve numpy<2 + pandas<3, where neither dependency triggers numpy.typing at import time. The uv.lock file does pin numpy 2.x, but this only protects users who install with uv — pip users have no such guarantee.

Upstream Dependency Protection

We investigated whether any dependency in the import chain triggers numpy.typing before core/predict.py is loaded. The chain is:

main.py → import numpy → import onnxruntime → import PyQt6 → ... → try: from core.predict import CannotModel
  • pandas: declared in pyproject.toml but not imported by main.py or core/predict.py — never loaded before the affected code. Even if pandas is installed, only pandas >= 3.0 triggers numpy.typing at import time.
  • PyQt6, onnxruntime, torch: none trigger numpy.typing.

Impact

The crash in core/predict.py is caught by a try/except in main.py that silently falls back to the ONNX backend:

try:
    from core.predict import CannotModel
    logger.info("Using PyTorch model for predictions.")
except:
    from core.predict_onnx import CannotModel
    logger.info("Using ONNX model for predictions.")

So numpy<2 users do not see a hard crash, but the PyTorch backend is silently unavailable — they get the ONNX fallback without any indication of the underlying cause.

Solution

Either:

  1. Add numpy>=2 to pyproject.toml:
"numpy>=2",  # was: "numpy"
  1. Or add a defensive import in core/predict.py:
import numpy.typing  # ensures np.typing.ArrayLike works on numpy<2
  1. Or add from __future__ import annotations to defer annotation evaluation.

References

  • NumPy 2.0 release notes — numpy.typing exposed as module attribute via __getattr__
  • Similar fix: numexpr#540

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions