Replace the Buck stub tests with one shared harness Summary: The torch and numpy stub packages each carried their own near-duplicate `run_pyrefly.py`, and the two had drifted: numpy could run Pyrefly out of Buck but not from a release build, torch could do the reverse. Adding a third package for jax would have meant a third copy and a third set of gaps. The runtime side had the same problem from the other direction, with the Buck targets and the GitHub workflow building their environments in completely different ways, so a green run in one said little about the other. Factor the parts that do not vary between packages into `shape_testing.py`: a `Suite` describing a named group of test files, resolution of the Pyrefly binary and of the virtualenv, and the two runners. A package now supplies only its `suites.py` plus thin entry points, so jax will be additive rather than another copy. Delete the Buck stub test targets rather than port them. They were a second, divergent way to run the same checks, and two of them built torch from source to do it. Everything now goes through one runner, so `test.py`, the internal Sandcastle job and the GitHub job differ only in where the Pyrefly binary comes from; `--buck` selects it in an internal checkout. The stub `python_library` and search-path targets stay, because they are how internal tooling and the porting skills point Pyrefly at the stubs. Separate bootstrapping from running, which is the main design constraint here. `bootstrap_venv.py` is the only thing that touches the network; the runners never create anything and fail with a message naming the fix instead. That matters because on a Meta machine the download needs fwdproxy, and a sandboxed agent cannot do it at all without being relaunched with `--secure-internet-mode`. Keeping the two apart means everything except bootstrap works offline, and the one step that cannot is reported clearly rather than hanging. One virtualenv at `~/.tensor-shapes-venv` serves all the libraries, since the runtime tests only build arrays and read shapes. Type checking needs no virtualenv at all: Pyrefly resolves the stubs through `--search-path` and never imports the real library. `run_tests.py --static-only` exposes that, and the missing-virtualenv error advertises it, because it is the usual mode when working on Pyrefly itself rather than on the stubs. Pin the libraries, and pin them to CPU-only builds. These tests assert the shapes the libraries actually produce, so an unpinned minor bump can turn a correct stub red. Shape checking never runs a kernel, so the CUDA stack is pure cost: the resulting virtualenv is 1.3G against 5.1G for a CUDA one. Run everything as a single job on both CI systems -- `fbcode//pyrefly:oss`'s sibling `:tensor_shapes` internally, one set of steps on GitHub -- rather than one job per library. The whole suite takes about 25 seconds, so splitting it would cost more in scheduling than it catches. The internal job installs `uv` when the image does not provide it, the way the neighbouring continuous jobs bootstrap their own tooling. Two behaviors are preserved deliberately. `GRADUAL_SHAPE_RUNTIME_TESTS` is now honored by the shared runner: a test whose static shape is gradual may use plain runtime assertions, because `assert_shape` still demands an exact static shape. And the two numpy-behavior tests from the deleted `numpy_runtime_test` wrapper move into `test/test_indexing.py`, where they keep asserting that NumPy rejects float array indices and mismatched paired index lengths at runtime. Pyrefly does not reject either statically, so they carry no inline error expectation and a comment records the gap. On GitHub, type checking runs on the whole matrix and only the runtime half is Ubuntu-only. Type checking needs no virtualenv, and the runners carry Windows-specific interpreter and `.exe` path handling that nothing else would exercise, so restricting it would leave that code untested on the only platform it exists for. The runtime half is genuinely platform independent, so installing torch and jax three times to assert the same shapes would be waste. Differential Revision: D117306584
Pyrefly is a type checker and language server for Python, which provides lightning-fast type checking along with IDE features such as code navigation, semantic highlighting, and code completion. It is available as a command-line tool and an extension for popular IDEs and editors such as VSCode, Neovim, Zed, and more.
See the Pyrefly website for full documentation and how to add Pyrefly to your editor of choice.
Pyrefly's current development status is stable.
pyrefly init, silence existing errors with pyrefly suppress, and generate type annotations with pyrefly infer. Start with one file and expand at your own pace.pip install pyreflyPyrefly releases new minor versions (1.x.0) monthly and patch versions in between as-needed for critical fixes. Pyrefly does not follow strict semantic versioning: minor versions contain more significant changes than patch versions, but any version may introduce new type errors and other breaking changes. The pyrefly suppress command can be used to easily silence errors when upgrading to a new version.
If you have questions or would like to report a bug, please create an issue.
See our contributing guide and architecture overview for information on how to contribute to Pyrefly.
Join our Discord to chat about Pyrefly and types. This is also where we hold biweekly office hours.