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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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