"""Load-bearing gates on two claims the PUBLISHED surface makes about itself. AAA+ criterion A5 is that no claim on the public surface is untrue. Two of this repo's claims are made in prose that no test could see, and both drift silently: 1. ``env.template`` tells the reader which credential the AZURE profile resolves. It said ``DefaultAzureCredential`` while :mod:`portfolio_optimiser.backends` has never constructed one — Fase 4b picks ``ManagedIdentityCredential`` or ``AzureCliCredential`` by environment, and Learn's MAF guidance names the specific credential *over* ``DefaultAzureCredential`` deliberately. 2. ``README.md`` publishes a wheel-install command that spells the wheel's FILENAME, and a wheel filename carries the version. A version bump moves the file the build produces without touching the README, leaving a stranger with an install command for a file that does not exist. Both gates read the source artefacts as RAW TEXT, because that is the only thing that can see prose. Both are LINE-ANCHORED rather than substring-matched: ``backends.py`` NAMES ``DefaultAzureCredential`` four times in the comments that explain why it is not used, so a whole-file substring check would be red on exactly the prose it protects (this repo's 08-09 defect class, and the reason the 4e ``azure.yaml`` gate is line-anchored too). Each positive assertion is paired with a CONTROL that the thing being searched for is actually present. An extractor that silently finds nothing makes a gate that can only ever be green, which proves nothing. """ from __future__ import annotations import re from pathlib import Path import pytest _REPO_ROOT = Path(__file__).resolve().parents[1] _ENV_TEMPLATE = _REPO_ROOT / "env.template" _README = _REPO_ROOT / "README.md" _PYPROJECT = _REPO_ROOT / "pyproject.toml" _BACKENDS = _REPO_ROOT / "src" / "portfolio_optimiser" / "backends.py" # The credential is chosen on ONE assignment statement. Reading the credential names off that line — # rather than off the whole module — is what keeps the explanatory comments out of the measurement. _CREDENTIAL_ASSIGNMENT = re.compile(r"^\s*credential\s*=\s*(?P.+)$", re.MULTILINE) _CREDENTIAL_CALL = re.compile(r"(\w*Credential)\s*\(") # A wheel filename spells the distribution, the version and the tags. The version is the drifting part. _WHEEL_FILENAME = re.compile(r"portfolio_optimiser-(?P[0-9][^-\s]*)-py3-none-any\.whl") # `[project]`'s own version line: the value hatchling stamps into the wheel filename. _PROJECT_VERSION = re.compile(r'^version\s*=\s*"(?P[^"]+)"', re.MULTILINE) def _constructed_credentials() -> set[str]: """The credential classes ``backends.py`` actually constructs, read off the assignment line.""" match = _CREDENTIAL_ASSIGNMENT.search(_BACKENDS.read_text(encoding="utf-8")) if match is None: return set() return set(_CREDENTIAL_CALL.findall(match.group("expr"))) def _built_version() -> str: match = _PROJECT_VERSION.search(_PYPROJECT.read_text(encoding="utf-8")) assert match is not None, "pyproject.toml has no [project] version line" return match.group("version") # -------------------------------------------------------------------------------------------- # Control: the extractors find something. Without these, every gate below could pass vacuously. # -------------------------------------------------------------------------------------------- def test_credential_extractor_finds_the_assignment() -> None: """CONTROL. If the assignment is reshaped, the gates below must fail loudly, not silently pass.""" constructed = _constructed_credentials() assert len(constructed) == 2, ( "expected backends.py to construct exactly two credentials on one assignment; " f"the extractor found {sorted(constructed)}" ) assert all(name.endswith("Credential") for name in constructed) def test_readme_publishes_a_wheel_install_command() -> None: """CONTROL. The version gate below is only meaningful while the README names a wheel file.""" found = _WHEEL_FILENAME.findall(_README.read_text(encoding="utf-8")) assert found, ( "README.md no longer spells a wheel filename — the version gate has nothing to guard" ) # -------------------------------------------------------------------------------------------- # A5 — env.template describes the credential the code actually uses # -------------------------------------------------------------------------------------------- def test_env_template_names_the_credentials_backends_constructs() -> None: """Every credential the AZURE path can construct is named in the template the operator copies.""" template = _ENV_TEMPLATE.read_text(encoding="utf-8") missing = sorted(name for name in _constructed_credentials() if name not in template) assert not missing, ( f"env.template does not name {missing}, which backends.py constructs. An operator " "reading the template cannot tell which identity the AZURE profile will use." ) def test_env_template_does_not_claim_default_azure_credential() -> None: """No line may present ``DefaultAzureCredential`` as the resolution mechanism. Line-anchored on purpose. ``backends.py`` names the class in prose to explain why it is NOT used, and that explanation is legitimate; what is not legitimate is the template telling an operator that resolution goes through a credential the code never constructs. """ offending = [ f"env.template:{number}: {line.strip()}" for number, line in enumerate(_ENV_TEMPLATE.read_text(encoding="utf-8").splitlines(), 1) if "DefaultAzureCredential" in line ] assert not offending, ( "env.template claims a credential backends.py never constructs:\n" + "\n".join(offending) ) # -------------------------------------------------------------------------------------------- # A5 — the published install command names the file the build actually produces # -------------------------------------------------------------------------------------------- def test_readme_wheel_command_cites_the_built_version() -> None: """The wheel filename in the README must carry the version hatchling will stamp on it.""" built = _built_version() cited = sorted(set(_WHEEL_FILENAME.findall(_README.read_text(encoding="utf-8")))) drifted = [version for version in cited if version != built] assert not drifted, ( f"README.md tells a reader to install portfolio_optimiser-{drifted[0]}-py3-none-any.whl, " f"but the build produces version {built}. The published install command names a file that " "does not exist." ) @pytest.mark.parametrize("artefact", [_ENV_TEMPLATE, _README, _PYPROJECT, _BACKENDS]) def test_guarded_artefacts_exist(artefact: Path) -> None: """CONTROL. A missing artefact must fail here rather than turn a gate into a no-op.""" assert artefact.is_file(), f"{artefact} is missing; the gates above would read nothing"