Minimal reproducer for astral-sh/ty#3833
This is a dependency-free reduction of astral-sh/ty#3833, which reports that ty hangs while resolving pandas.Series.__mul__ against a NumPy ndarray when using NumPy 2.5.0's stubs.
GitHub Gists have a flat filename namespace, so the two stub files have path-prefixed names here. Restore the package layout before running ty:
mkdir -p numpy/_typing
cp numpy__init__.pyi numpy/__init__.pyi
cp numpy__typing__init__.pyi numpy/_typing/__init__.pyiThe resulting tree is:
.
├── repro.py
└── numpy
├── __init__.pyi
└── _typing
└── __init__.pyi
First, verify that the reduced stubs are internally valid:
uvx ty@0.0.52 check --python-version 3.13 \
numpy/__init__.pyi numpy/_typing/__init__.pyiThis prints:
All checks passed!
Then check the reproducer under a timeout:
timeout 30 uvx ty@0.0.52 check --python-version 3.13 repro.pyty produces no output and is killed after 30 seconds (exit 124).
The issue's original source was reproduced with Python 3.13, ty 0.0.52, pandas 2.3.3, and pandas-stubs 3.0.3.260530:
| NumPy version | Result |
|---|---|
| 2.5.0 | No output; timed out after 20 seconds (exit 124) |
| 2.4.6 | All checks passed! |
- pandas and pandas-stubs can be removed completely.
- The pandas side reduces to one generic
Series.__mul__signature whose argument isSupportsRMul[S2_contra, S2_NSDT]. - The NumPy side requires exactly five
ndarray.__rmul__overloads. Removing any one makes ty terminate successfully. - NumPy's
_NestedSequenceprotocol reduces to a single recursive__reversed__method. - The
numpy↔numpy._typingmodule cycle is essential. Inlining the two stubs into one module makes the hang disappear, which is why this reproducer contains two local stub modules. - No diagnostic code is emitted in the failing case because ty hangs before producing output.
The issue body presents its PEP 723 script with uvx ty@0.0.52 check repro.py. In a clean directory, uvx does not install the script's PEP 723 dependencies for this command, so that literal invocation reports unresolved-import for NumPy and pandas. The original A/B result above was verified in isolated Python 3.13 virtual environments containing the exact stated pins; this reduced version needs no third-party packages.