Files
troupe-standup/wizard-work/spark/test_python_env_check.py
T
ledger bda365c7c8 spark: python-env-check declares the lane's real deps and can fail (Q120)
The old check imported json, subprocess and datetime -- all stdlib -- so
its failure condition was unreachable, and its version-reporting helper
check_package was defined and never called.  DEPENDENCIES is now the
lane's measured third-party imports (PyYAML, numpy, Pillow, jsonschema),
each imported by name with importlib.metadata version; missing -> rc 1,
broken -> rc 1, usage error -> rc 2.  email_validator is not declared:
spark's own email_validator.py is a local stdlib-only module.

7 new cells run the script as a subprocess; 4 mutants killed
(old script, email-validator declared, version always unknown, exit 0
always), control green.  Queue Q120 closed with the record appended and
docs/queue-index.md re-rendered in the same commit.
2026-10-29 04:34:54 +00:00

130 lines
4.8 KiB
Python

#!/usr/bin/env python3
"""Cells for wizard-work/spark/python-env-check.py (queue Q120).
The script under test is run as a subprocess, exactly as an operator runs
it; nothing here imports it. The red cell picks its missing package by
measuring the host first, so it is a real absence rather than a name the
test hopes is absent.
Run: python3 -m unittest discover -p 'test_python_env_check.py' -v
(from wizard-work/spark, or by path from anywhere)
"""
import importlib.util
import json
import os
import subprocess
import sys
import unittest
HERE = os.path.dirname(os.path.abspath(__file__))
SCRIPT = os.path.join(HERE, "python-env-check.py")
# Real, widely-installed packages the spark lane does not depend on. The red
# cell requires whichever of these the host genuinely lacks.
RED_CANDIDATES = ("flask", "django", "pandas", "scipy", "tensorflow", "torch", "black")
def run_script(*args, cwd=None):
proc = subprocess.run(
[sys.executable, SCRIPT] + list(args),
cwd=cwd or HERE,
capture_output=True,
text=True,
)
return proc
def absent_package():
"""Return the first candidate module that cannot be found on this host."""
for name in RED_CANDIDATES:
try:
found = importlib.util.find_spec(name)
except (ImportError, ValueError):
found = None
if found is None:
return name
return None
class EnvCheckContract(unittest.TestCase):
def setUp(self):
self.proc = run_script()
self.assertEqual(
self.proc.returncode in (0, 1),
True,
"expected rc 0 or 1, got %r: %s" % (self.proc.returncode, self.proc.stderr),
)
self.report = json.loads(self.proc.stdout)
def test_declared_list_is_not_the_standard_library(self):
# The defect Q120 filed: the only names checked were json/subprocess/
# datetime, so no healthy interpreter could ever fail this script.
packages = self.report["components"]["packages"]
self.assertTrue(packages, "no packages reported at all")
stdlib = set(getattr(sys, "stdlib_module_names", ()))
for import_name in packages:
self.assertNotIn(
import_name,
stdlib,
"%r is a standard-library module, not a lane dependency" % import_name,
)
def test_declared_list_is_the_lane_dependencies(self):
packages = self.report["components"]["packages"]
self.assertEqual(
set(packages), {"yaml", "numpy", "PIL", "jsonschema"}
)
# email_validator is the lane's own stdlib-only module, not the PyPI
# distribution; declaring it would test something the lane never uses.
self.assertNotIn("email_validator", packages)
def test_every_declared_dependency_reports_a_version(self):
packages = self.report["components"]["packages"]
for import_name, result in packages.items():
self.assertEqual(result["status"], "ok", "%s: %r" % (import_name, result))
self.assertIn("version", result)
self.assertIn("distribution", result)
self.assertFalse(
result["version"] in ("", "unknown"),
"%s reported no version: %r" % (import_name, result),
)
def test_all_ok_agrees_with_the_missing_list(self):
self.assertEqual(self.report["all_ok"], self.report["missing"] == [])
self.assertEqual(self.proc.returncode, 0 if self.report["all_ok"] else 1)
def test_genuinely_absent_package_turns_the_reading_red(self):
name = absent_package()
if name is None:
self.skipTest(
"every candidate %r is installed here; no real package to "
"prove the red path with" % (RED_CANDIDATES,)
)
proc = run_script("--require", name)
self.assertEqual(proc.returncode, 1, proc.stdout + proc.stderr)
report = json.loads(proc.stdout)
self.assertFalse(report["all_ok"])
self.assertEqual(report["missing"], [name])
result = report["components"]["packages"][name]
self.assertEqual(result["status"], "missing")
self.assertIn(name, result["error"])
# The healthy declared dependencies still report alongside it.
self.assertEqual(report["dependencies_declared"], 5)
self.assertEqual(
report["components"]["packages"]["yaml"]["status"], "ok"
)
def test_usage_error_is_rc_two(self):
proc = run_script("--require")
self.assertEqual(proc.returncode, 2, proc.stderr)
def test_same_reading_from_a_different_cwd(self):
other = run_script(cwd="/")
self.assertEqual(other.returncode, self.proc.returncode)
self.assertEqual(json.loads(other.stdout)["missing"], self.report["missing"])
if __name__ == "__main__":
unittest.main(verbosity=2)