from __future__ import annotations import os import shutil import sys from pathlib import Path import pytest # Ensure editable install's src path is on sys.path when running from checkout. ROOT = Path(__file__).resolve().parents[1] SRC = ROOT / "src" if str(SRC) not in sys.path: sys.path.insert(0, str(SRC)) @pytest.fixture def tiny_client(tmp_path: Path) -> Path: """Copy the checked-in tiny_client fixture into a tmp dir and return it.""" src = Path(__file__).parent / "fixtures" / "tiny_client" dst = tmp_path / "client" shutil.copytree(src, dst) return dst @pytest.fixture def make_manifest_script() -> Path: return Path("/home/jann/metin/repos/m2dev-client/scripts/make-manifest.py") @pytest.fixture def sign_manifest_script() -> Path: return Path("/home/jann/metin/repos/m2dev-client/scripts/sign-manifest.py") @pytest.fixture(autouse=True) def reset_env(monkeypatch): # Don't let ambient env vars bleed into tests. for key in ("METIN_RELEASE_MAKE_MANIFEST", "METIN_RELEASE_SIGN_MANIFEST"): monkeypatch.delenv(key, raising=False) yield @pytest.fixture def test_keypair(tmp_path: Path) -> tuple[Path, str]: """Generate an ephemeral Ed25519 keypair, write the private key mode 600. Returns (private_key_path, public_key_hex). """ from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey priv = Ed25519PrivateKey.generate() raw = priv.private_bytes( encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption(), ) key_path = tmp_path / "key" key_path.write_bytes(raw) os.chmod(key_path, 0o600) pub_hex = priv.public_key().public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw, ).hex() return key_path, pub_hex