What a Python project DECLARES about its own layout: import roots (the src
layout every packaging backend spells differently) and pytest's testpaths.
The metadata is parsed by PYTHON'S OWN parsers inside a GraalPy context --
tomllib for pyproject.toml, configparser for setup.cfg / pytest.ini
/ tox.ini -- never a regex over the file text. The Python side
(resources/vis-python/project_config.py) returns RAW declared strings;
everything host-shaped (~ expansion, resolution against the project dir,
existence, canonicalisation, dedup, python.source_paths config) lives here.
Inference is purely declarative: a project without such metadata gets
nothing inferred, and python.source_paths is how a user says it outright.
Every failure degrades to nothing rather than breaking the caller.
What a Python project DECLARES about its own layout: import roots (the `src` layout every packaging backend spells differently) and pytest's `testpaths`. The metadata is parsed by PYTHON'S OWN parsers inside a GraalPy context -- `tomllib` for `pyproject.toml`, `configparser` for `setup.cfg` / `pytest.ini` / `tox.ini` -- never a regex over the file text. The Python side (`resources/vis-python/project_config.py`) returns RAW declared strings; everything host-shaped (`~` expansion, resolution against the project dir, existence, canonicalisation, dedup, `python.source_paths` config) lives here. Inference is purely declarative: a project without such metadata gets nothing inferred, and `python.source_paths` is how a user says it outright. Every failure degrades to nothing rather than breaking the caller.
(declared-config ctx dir)Raw layout dir's packaging metadata declares, read inside ctx:
{:import-roots ["src" …] :testpaths ["tests" …]}
in declaration order, exactly as written. Sources:
[tool.setuptools.packages.find] where = ["src"] [tool.setuptools] package-dir = {"" = "src"} [tool.poetry] packages = [{include = "pkg", from = "src"}] [tool.hatch.build.targets.wheel] packages = ["src/pkg"] [tool.pdm.build] package-dir = "src" [tool.pytest.ini_options] pythonpath = ["src"] testpaths = ["tests"] setup.cfg [options] package_dir = =src setup.cfg [tool:pytest] / pytest.ini / tox.ini [pytest] pythonpath / testpaths
Unreadable or absent metadata yields empty vectors, never a throw; a read that
FAILED (as opposed to one that found nothing) also carries :error with why,
so a caller can say so instead of reporting a project with no layout. The
caller's globals are left exactly as they were found.
Raw layout `dir`'s packaging metadata declares, read inside `ctx`:
{:import-roots ["src" …] :testpaths ["tests" …]}
in declaration order, exactly as written. Sources:
[tool.setuptools.packages.find] where = ["src"]
[tool.setuptools] package-dir = {"" = "src"}
[tool.poetry] packages = [{include = "pkg", from = "src"}]
[tool.hatch.build.targets.wheel] packages = ["src/pkg"]
[tool.pdm.build] package-dir = "src"
[tool.pytest.ini_options] pythonpath = ["src"] testpaths = ["tests"]
setup.cfg [options] package_dir = =src
setup.cfg [tool:pytest] / pytest.ini / tox.ini [pytest] pythonpath / testpaths
Unreadable or absent metadata yields empty vectors, never a throw; a read that
FAILED (as opposed to one that found nothing) also carries `:error` with why,
so a caller can say so instead of reporting a project with no layout. The
caller's globals are left exactly as they were found.(existing-paths dir paths)(existing-paths dir paths pred)paths (raw, relative to dir) reduced to the canonical paths of the
entries that actually exist, in declaration order, without duplicates.
pred (default: exists) decides what counts.
`paths` (raw, relative to `dir`) reduced to the canonical paths of the entries that actually exist, in declaration order, without duplicates. `pred` (default: exists) decides what counts.
(import-roots ctx dir)Import roots for dir, read through the already-built ctx: the ones
configured in python.source_paths first, then whatever the packaging
metadata declares. Canonical paths of directories that actually exist, in
declaration order, so vis-agent python -m pytest tests/ imports the project
the same way an explicit PYTHONPATH=src invocation would.
Import roots for `dir`, read through the already-built `ctx`: the ones configured in `python.source_paths` first, then whatever the packaging metadata declares. Canonical paths of directories that actually exist, in declaration order, so `vis-agent python -m pytest tests/` imports the project the same way an explicit `PYTHONPATH=src` invocation would.
(project-layout dir){:import-roots [abs…] :testpaths [abs…]} for dir, read in a THROWAWAY
trusted GraalPy context (~130ms) -- for callers that have no context of
their own, such as the run_tests handler. Both are canonical paths of
entries that exist; either may be empty.
A FAILED read is retried once (a cold context can lose its first attempt) and,
if it fails again, the map carries :warning. Degrading silently to "no
import roots" is what makes a src-layout project report bogus
No module named <pkg> errors from the user's own tests.
`{:import-roots [abs…] :testpaths [abs…]}` for `dir`, read in a THROWAWAY
trusted GraalPy context (~130ms) -- for callers that have no context of
their own, such as the `run_tests` handler. Both are canonical paths of
entries that exist; either may be empty.
A FAILED read is retried once (a cold context can lose its first attempt) and,
if it fails again, the map carries `:warning`. Degrading silently to "no
import roots" is what makes a `src`-layout project report bogus
`No module named <pkg>` errors from the user's own tests.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |