ruff
dfd6ed05 - [ty] mdtests with external dependencies (#20904)

Commit
28 days ago
[ty] mdtests with external dependencies (#20904) ## Summary This PR adds the possibility to write mdtests that specify external dependencies in a `project` section of TOML blocks. For example, here is a test that makes sure that we understand Pydantic's dataclass-transform setup: ````markdown ```toml [environment] python-version = "3.12" python-platform = "linux" [project] dependencies = ["pydantic==2.12.2"] ``` ```py from pydantic import BaseModel class User(BaseModel): id: int name: str user = User(id=1, name="Alice") reveal_type(user.id) # revealed: int reveal_type(user.name) # revealed: str # error: [missing-argument] "No argument provided for required parameter `name`" invalid_user = User(id=2) ``` ```` ## How? Using the `python-version` and the `dependencies` fields from the Markdown section, we generate a `pyproject.toml` file, write it to a temporary directory, and use `uv sync` to install the dependencies into a virtual environment. We then copy the Python source files from that venv's `site-packages` folder to a corresponding directory structure in the in-memory filesystem. Finally, we configure the search paths accordingly, and run the mdtest as usual. I fully understand that there are valid concerns here: * Doesn't this require network access? (yes, it does) * Is this fast enough? (`uv` caching makes this almost unnoticeable, actually) * Is this deterministic? ~~(probably not, package resolution can depend on the platform you're on)~~ (yes, hopefully) For this reason, this first version is opt-in, locally. ~~We don't even run these tests in CI (even though they worked fine in a previous iteration of this PR).~~ You need to set `MDTEST_EXTERNAL=1`, or use the new `-e/--enable-external` command line option of the `mdtest.py` runner. For example: ```bash # Skip mdtests with external dependencies (default): uv run crates/ty_python_semantic/mdtest.py # Run all mdtests, including those with external dependencies: uv run crates/ty_python_semantic/mdtest.py -e # Only run the `pydantic` tests. Use `-e` to make sure it is not skipped: uv run crates/ty_python_semantic/mdtest.py -e pydantic ``` ## Why? I believe that this can be a useful addition to our testing strategy, which lies somewhere between ecosystem tests and normal mdtests. Ecosystem tests cover much more code, but they have the disadvantage that we only see second- or third-order effects via diagnostic diffs. If we unexpectedly gain or lose type coverage somewhere, we might not even notice (assuming the gradual guarantee holds, and ecosystem code is mostly correct). Another disadvantage of ecosystem checks is that they only test checked-in code that is usually correct. However, we also want to test what happens on wrong code, like the code that is momentarily written in an editor, before fixing it. On the other end of the spectrum we have normal mdtests, which have the disadvantage that they do not reflect the reality of complex real-world code. We experience this whenever we're surprised by an ecosystem report on a PR. That said, these tests should not be seen as a replacement for either of these things. For example, we should still strive to write detailed self-contained mdtests for user-reported issues. But we might use this new layer for regression tests, or simply as a debugging tool. It can also serve as a tool to document our support for popular third-party libraries. ## Test Plan * I've been locally using this for a couple of weeks now. * `uv run crates/ty_python_semantic/mdtest.py -e`
Author
Parents
Loading