flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
_bootstrap.py
Go to the documentation of this file.
1"""Resolve `peclet.flow` for the scripts in this directory (and tests/study, tests/regression, one
2level down) -- one place instead of a copy-pasted sys.path.insert at the top of every script.
3
4Precedence, and why:
5
6 1. If `import peclet.flow` already succeeds with `sys.path` exactly as the interpreter set it up
7 (PYTHONPATH, an editable install, a wheel, ...) -- use it, and insert nothing. Whatever the
8 caller already arranged is what gets tested; a script must never second-guess it.
9 2. Otherwise, if PECLET_FLOW_BUILD is set (or an explicit build dir is passed in, e.g. from a
10 script's own --build flag), insert that directory at the FRONT of sys.path and import from
11 there.
12 3. Otherwise, fail loudly. There is no default build directory.
13
14A silent fallback to some `build*/` guess is exactly the defect this module exists to close: every
15`flow/scripts/*.py` used to `sys.path.insert(0, ...SDFLOW_BUILD default build_mpi...)` UNCONDITIONALLY,
16ahead of anything PYTHONPATH set up. `PYTHONPATH=$PWD/build python scripts/verify_poiseuille_flow.py`
17therefore silently tested `build_mpi` instead -- ten days and ~50 commits stale on 2026-09-11 -- and
18kept printing PASS the whole time (docs/RELEASE_PREP.md #1.3). An explicit failure that names both
19ways to fix it costs one line; a wrong PASS costs a release. `SDFLOW_BUILD` itself is retired (the
20suite-wide sdflow -> flow rename, QUALITY_PLAN D1: no compatibility aliases) in favour of
21PECLET_FLOW_BUILD.
22
23Every caller prints, to stderr, exactly which `peclet.flow` it ended up with -- so the reader of a
24PASS/FAIL knows which binary produced it.
25"""
26import os
27import sys
28
29
30def ensure_flow(explicit_build=None):
31 """Import and return the `peclet.flow` module, resolved per the module docstring's precedence.
32
33 `explicit_build`, if given, is a directory to try (e.g. from a script's own --build CLI flag)
34 with the same standing as PECLET_FLOW_BUILD: consulted only when `peclet.flow` is not already
35 importable, and only if PECLET_FLOW_BUILD itself is unset.
36
37 Always prints one line to stderr naming the resolved module file or inserted directory. Raises
38 SystemExit with a corrective message if `peclet.flow` cannot be found at all.
39 """
40 try:
41 import peclet.flow as flow
42 except ImportError:
43 build_dir = os.environ.get("PECLET_FLOW_BUILD") or explicit_build
44 if not build_dir:
45 raise SystemExit(
46 "peclet.flow not importable: set PYTHONPATH=<build tree> "
47 "(e.g. PYTHONPATH=$PWD/build) or PECLET_FLOW_BUILD=<build tree> "
48 "(e.g. PECLET_FLOW_BUILD=$PWD/build_mpi) and rerun."
49 )
50 build_dir = os.path.abspath(build_dir)
51 sys.path.insert(0, build_dir)
52 try:
53 import peclet.flow as flow
54 except ImportError as exc:
55 raise SystemExit(
56 f"peclet.flow not importable from build dir {build_dir!r}: {exc}\n"
57 "Fix: point PECLET_FLOW_BUILD (or PYTHONPATH) at a directory containing the "
58 "built peclet/flow/_flow*.so."
59 ) from exc
60 print(f"peclet.flow: using build dir {build_dir} -> {flow.__file__}", file=sys.stderr)
61 return flow
62 print(f"peclet.flow: already importable -> {flow.__file__}", file=sys.stderr)
63 return flow