STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_package.py
Go to the documentation of this file.
1"""Phase 00's exit criterion, as a test.
2
3The whole point of this phase is that ``import feedtwin`` works from two very
4different environments -- the feed-twin API container and EngineDesign's
5optimizer process -- and that the physics stack it needs is actually resolvable
6in both. That is not a formality: an optimizer that discovers a missing CoolProp
715 minutes into a Layer X run has wasted the run.
8"""
9
10from __future__ import annotations
11
12import importlib
13import importlib.metadata
14import subprocess
15import sys
16
17import pytest
18
19import feedtwin
20
21#: Everything whose absence would make a physics answer impossible, not merely
22#: degraded. Kept in step with the dependency list in pyproject.toml.
23REQUIRED_STACK = ["numpy", "scipy", "CoolProp", "fluids", "ht"]
24
25
27 assert feedtwin.__version__
28
29
31 """``__init__.py`` is the only place the version is written.
32
33 pyproject.toml reads it from there via ``[tool.setuptools.dynamic]``, so the
34 two cannot disagree in a fresh install. They can still disagree after
35 bumping ``__version__`` without reinstalling, and that matters: run
36 provenance stamps the attribute while anything resolving the distribution
37 sees the metadata. This turns that into a failed test rather than two
38 versions of the truth in a results file.
39 """
40 installed = importlib.metadata.version("feedtwin")
41 assert installed == feedtwin.__version__, (
42 f"installed metadata says {installed}, feedtwin.__version__ says "
43 f"{feedtwin.__version__} -- reinstall with `pip install -e lib/feedtwin`"
44 )
45
46
48 """The library must stay importable in a process with no web stack.
49
50 EngineDesign's optimizer will import this package directly (ADR-0001). If a
51 FastAPI import ever creeps into the physics -- through a Pydantic model that
52 drags in starlette, most likely -- that call path acquires a dependency it
53 has no use for, and the separation this package exists to maintain is gone.
54
55 Checked in a subprocess, not against this process's ``sys.modules``: pytest
56 itself, or a sibling test, may legitimately have imported a web framework
57 already, and asserting on a shared interpreter would make this pass or fail
58 on test ordering rather than on what feedtwin actually pulls in.
59 """
60 probe = (
61 "import sys; import feedtwin; "
62 "leaked = {'fastapi', 'starlette', 'uvicorn'} & set(sys.modules); "
63 "print(','.join(sorted(leaked)))"
64 )
65 result = subprocess.run(
66 [sys.executable, "-c", probe],
67 capture_output=True,
68 text=True,
69 check=True,
70 )
71
72 leaked = result.stdout.strip()
73 assert not leaked, f"importing feedtwin pulled in a web framework: {leaked}"
74
75
76@pytest.mark.parametrize("module", REQUIRED_STACK)
77def test_physics_stack_is_importable(module: str) -> None:
78 """Each dependency resolves in whatever environment is running these tests."""
79 assert importlib.import_module(module) is not None
80
81
83 """Run provenance covers the whole stack, not just feedtwin's own version."""
84 versions = feedtwin.stack_versions()
85
86 assert versions["feedtwin"] == feedtwin.__version__
87 assert versions["python"]
88
89 missing = [name for name in REQUIRED_STACK if versions.get(name) is None]
90 assert not missing, f"stack_versions() could not report versions for {missing}"
None test_physics_stack_is_importable(str module)
None test_stack_versions_reports_every_dependency()
None test_version_matches_installed_metadata()
None test_package_carries_no_web_framework()
None test_version_is_declared()