Skip to content

Commit a76cd7c

Browse files
committed
Abstract over platform differences
1 parent e2d299d commit a76cd7c

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

crates/red_knot_test/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,45 @@ typeshed = "/typeshed"
314314

315315
For more details, take a look at the [custom-typeshed Markdown test].
316316

317+
### Mocking a virtual environment
318+
319+
Mdtest supports mocking a virtual environment for a specific test at an arbitrary location, again
320+
using the `[environment]` configuration option:
321+
322+
````markdown
323+
```toml
324+
[environment]
325+
python = ".venv"
326+
```
327+
````
328+
329+
Red-knot will reject virtual environments that do not have valid `pyvenv.cfg` files at the
330+
virtual-environment directory root (here, `.venv/pyvenv.cfg`). However, if a `pyvenv.cfg` file does
331+
not have its contents specified by the test, mdtest will automatically generate one for you, to
332+
make mocking a virtual environment more ergonomic.
333+
334+
Mdtest also makes it easy to write Python packages to the mock virtual environment's
335+
`site-packages` directory using the `<path-to-site-packages>` magic path separator. This would
336+
otherwise be hard, due to the fact that the `site-packages` subdirectory in a virtual environment
337+
is located at a different relative path depending on the platform the virtual environment was
338+
created on. In the following test, mdtest will write the Python file to
339+
`.venv/Lib/site-packages/foo.py` in its in-memory filesystem used for the test if the test is being
340+
executed on Windows, and `.venv/lib/python3.13/site-packages/foo.py` otherwise:
341+
342+
````markdown
343+
```toml
344+
[environment]
345+
python = ".venv"
346+
python-version = "3.13"
347+
```
348+
349+
`.venv/<path-to-site-packages>/foo.py`:
350+
351+
```py
352+
X = 1
353+
```
354+
````
355+
317356
## Documentation of tests
318357

319358
Arbitrary Markdown syntax (including of course normal prose paragraphs) is permitted (and ignored by

crates/red_knot_test/src/lib.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ fn run_test(
162162
let custom_typeshed_path = test.configuration().typeshed();
163163
let python_path = test.configuration().python();
164164
let python_version = test.configuration().python_version().unwrap_or_default();
165+
165166
let mut typeshed_files = vec![];
166167
let mut has_custom_versions_file = false;
167168
let mut has_custom_pyvenv_cfg_file = false;
@@ -178,7 +179,7 @@ fn run_test(
178179
"Supported file types are: py (or python), pyi, text, cfg and ignore"
179180
);
180181

181-
let full_path = embedded.full_path(&project_root);
182+
let mut full_path = embedded.full_path(&project_root);
182183

183184
if let Some(typeshed_path) = custom_typeshed_path {
184185
if let Ok(relative_path) = full_path.strip_prefix(typeshed_path.join("stdlib")) {
@@ -192,6 +193,24 @@ fn run_test(
192193
if let Ok(relative_path) = full_path.strip_prefix(python_path) {
193194
if relative_path.as_str() == "pyvenv.cfg" {
194195
has_custom_pyvenv_cfg_file = true;
196+
} else {
197+
let mut new_path = SystemPathBuf::new();
198+
for component in full_path.components() {
199+
let component = component.as_str();
200+
if component == "<path-to-site-packages>" {
201+
if cfg!(target_os = "windows") {
202+
new_path.push("Lib");
203+
new_path.push("site-packages");
204+
} else {
205+
new_path.push("lib");
206+
new_path.push(format!("python{python_version}"));
207+
new_path.push("site-packages");
208+
}
209+
} else {
210+
new_path.push(component);
211+
}
212+
}
213+
full_path = new_path;
195214
}
196215
}
197216
}

0 commit comments

Comments
 (0)