File size: 4,137 Bytes
551b309
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""Fail-closed integrity guard.

A signed file manifest ships inside the built wheel. On import the package
recomputes the hash of every shipped file and compares it to the manifest. Any
edit, overwrite, added file, or removed file trips the guard: the package marks
itself bricked and refuses to run.

Honest limit: this is tamper-evident, not tamper-proof. A user who edits the
guard itself, or deletes the manifest, disables the check, because the code runs
on their machine. No client-side mechanism can prevent that. What this does
guarantee is that any accidental or casual modification of a shipped file stops
the product working rather than running altered code silently.

The manifest is generated at build time (see hatch_build.py) and is absent from
the source tree, so an editable development checkout is not enforced.
"""

# Credit: @paparichens

from __future__ import annotations

import hashlib
import json
from collections.abc import Iterator
from pathlib import Path

MANIFEST_NAME = "_integrity_manifest.json"
MANIFEST_ALGORITHM = "sha256"
_SKIP_SUFFIXES = (".pyc", ".pyo")
_SKIP_DIRS = frozenset({"__pycache__"})

_bricked_reason: str | None = None


class IntegrityError(RuntimeError):
    """Raised when a shipped file has been altered, added, or removed."""


def _iter_files(root: Path) -> Iterator[Path]:
    for path in sorted(root.rglob("*")):
        if not path.is_file():
            continue
        if any(part in _SKIP_DIRS for part in path.relative_to(root).parts):
            continue
        if path.suffix in _SKIP_SUFFIXES:
            continue
        if path.name == MANIFEST_NAME:
            continue
        yield path


def _hash_file(path: Path) -> str:
    digest = hashlib.new(MANIFEST_ALGORITHM)
    with path.open("rb") as handle:
        for chunk in iter(lambda: handle.read(65536), b""):
            digest.update(chunk)
    return digest.hexdigest()


def build_manifest(root: Path) -> dict[str, object]:
    """Compute the manifest for a package directory."""
    files = {
        str(path.relative_to(root).as_posix()): _hash_file(path)
        for path in _iter_files(root)
    }
    return {"version": 1, "algorithm": MANIFEST_ALGORITHM, "files": files}


def verify_tree(root: Path) -> None:
    """
    Verify a package directory against its manifest.

    No manifest present means an unbuilt or editable tree, which is not
    enforced. A present manifest is enforced strictly.
    """
    manifest_path = root / MANIFEST_NAME
    if not manifest_path.exists():
        return

    try:
        manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
        expected = dict(manifest["files"])
    except (OSError, ValueError, KeyError, TypeError) as exc:
        raise IntegrityError("Integrity manifest is unreadable or malformed") from exc

    actual = {
        str(path.relative_to(root).as_posix()): _hash_file(path)
        for path in _iter_files(root)
    }

    added = sorted(set(actual) - set(expected))
    removed = sorted(set(expected) - set(actual))
    changed = sorted(
        name for name in expected.keys() & actual.keys() if expected[name] != actual[name]
    )

    if added or removed or changed:
        parts = []
        if changed:
            parts.append(f"modified: {', '.join(changed)}")
        if removed:
            parts.append(f"missing: {', '.join(removed)}")
        if added:
            parts.append(f"unexpected: {', '.join(added)}")
        raise IntegrityError(
            "Package integrity check failed (" + "; ".join(parts) + "). "
            "A shipped file was altered. Reinstall a clean copy: "
            "pip install --force-reinstall affix-huggingface"
        )


def enforce() -> None:
    """Run the guard for this installed package and remember the outcome."""
    global _bricked_reason
    try:
        verify_tree(Path(__file__).resolve().parent)
    except IntegrityError as exc:
        _bricked_reason = str(exc)
        raise


def ensure_intact() -> None:
    """Refuse to proceed once the guard has tripped."""
    if _bricked_reason is not None:
        raise IntegrityError(_bricked_reason)