NEO.K / MSSP 開源專案考古011-cpython-shelve
專案CPython shelve
授權PSF-2.0
檢視版本3.14.5
日期2026-08-11
來源upstream ↗

011 — CPython shelve 3.14.5:一個旗標改變了每一次讀取的意義

原專案 CPython Lib/shelve.py,PSF-2.0。本篇考察 3.14.5,250 行。 所有數字都是在這台機器上對這個直譯器量出來的。

python src/main.py            # 兩種模式、快取成長,以及重切與真 shelve 的逐格比對
python src/main.py --strict   # 重切跟真 shelve 不一致就 exit 1
python src/island_test.py     # 19 項檢查,其中 9 項直接跑 CPython 本體

為什麼選它

同日的範例 011 是這個實驗室第一則有狀態活得比行程久的範例。九天後路線轉向真實市場應用——電商、報表——而目前每一個機制都假設 src/ 底下一支沒有 UI、沒有持久化的程式。

shelve 是標準庫裡最小的持久化映射,三十年歷史,而它的一個旗標會改變每一次讀取的意義

  writeback    d[k].append(x) survives    d[k] is d[k]   objects held
  False        ['apple']                  False          0
  True         ['apple', 'pear']          True           1

同一個 API、同一個呼叫、相反的語義。唯一能分辨的觀察是 d[k] is d[k]——一行,而且沒有任何呼叫端會去看它。

原專案的結構地圖

shelve.py 250 行
Shelf.__getitem__ 9 行
Shelf.__setitem__ 7 行
公開類別 ShelfBsdDbShelfDbfilenameShelf
writeback 預設 False

上面五個數字由 main.py 對正在跑的直譯器重新量一次再跟 FMS 比對。第一次跑就抓到一個:我把 __setitem__ 宣告成 5 行,量到 7。那一列現在留著更正註記,因為它是整篇裡唯一能證明「重量測會失敗」的證據。

決定一切的是 9 行裡的 3 行:

def __getitem__(self, key):
    try:
        value = self.cache[key]
    except KeyError:
        f = BytesIO(self.dict[key.encode(self.keyencoding)])
        value = Unpickler(f).load()
        if self.writeback:
            self.cache[key] = value
    return value

if self.writeback: self.cache[key] = value 在一次讀取裡。 旗標叫做 writeback,而它做的第一件事是決定一次讀取要不要把東西留下來。

MSSP 重切

集合 裡面是什麼
FMS 旗標、它實際改變的四件事,以及 main.py 會重新量的五個數字
SCL 這個部署用哪一種交付策略,以及宣告是否必須被行為證明
SMS 重切的 Shelf、依名字解析、identity 探針,以及跑真 shelve 的探針
TMS 一種策略一個檔——各自宣告交回什麼、變動會不會存活,且不取用任何兄弟集合
DMS 兩種模式並排、與真 shelve 的比對,以及看不到的部分

唯一的結構改動是把布林旗標換成兩個具名單元,各自宣告自己交回什麼——而那份宣告是用跑的驗,不是用讀的:

  PASS  cached-reference: declared mutation_survives=True, measured True
  PASS  copy-on-read: declared mutation_survives=False, measured False
  PASS  a handout declaring copy semantics while caching is caught - declared False, measured True

第三列是鑽孔:一個宣告自己是複製語義、實作卻是快取的策略必須被抓到。沒有那一列,前兩列只是兩份互相同意的宣告——mssp-d-003 整串在講的形狀。

重切與真 shelve 每次執行都逐格比對,而第 3b 節故意用錯策略去證明那個比對會失敗:

  PASS  all 4 cells agree - 4/4
  PASS  using the wrong strategy for writeback=False breaks cells - so section 3 is a measurement, not a formality

什麼不適合拆

writeback=True 本身不是缺陷,不要修掉它。 它預設關閉、有寫文件,而且對知道自己在做什麼的呼叫端是對的——你要就地變動大結構時,它省掉一整輪讀出、改、寫回。

這跟昨天考古 010UNCHECKED_HASH 是同一個判斷:一個永遠不拒絕、或永遠不複製的模式,只要它把這件事說出來,就不是缺陷。 兩則的差別在說出來的方式——CPython 把 .pyc 的選擇寫進標頭的 flag bits,任何東西都讀得到;shelve 的選擇只存在於開檔那一行的呼叫端,而拿到 d 的人看不到它。

pickle 的來回也不適合拆掉。 它就是「複製」之所以可能的原因。

這次沒有解決什麼

第三個發現是在修掉我自己一個寫死的檢查時掉出來的。

第 4 節原本有一行 check("and nothing was written during them", True, ...)——一個斷言「這個讀取迴圈沒有寫任何東西」。那正是這個實驗室 2026-08-08 對考古 008 自己提出的缺陷:在量測漂移的那一節裡寫死 True

改成真的量它,答案跟我的斷言不一樣:

  PASS  a READ-ONLY session under writeback rewrites the medium at close - 1 of 1 files changed: store
  PASS  the same read-only session under the default does not - 1 of 1 files unchanged
  PASS  so the two differ, which is what makes either mean anything

writeback=True 下,一個只讀不寫的 session 在關閉時會把媒介整個重寫一次。 200 次純讀取留下 200 個物件,然後 close() 把它們全部寫回去。旗標的名字描述的是第四層後果,而第一層是「一次讀取會保留」。

量得到但這次沒量: 真實程式碼多常變動 shelf 交回來的東西;那些被保留的物件在一個 session 大小的工作量上實際佔多少。

這一則量不到: 預設是不是錯的——它是關的、有文件,而打開它要花的記憶體多數呼叫端不想付。以及野外的發生率——重現一次無聲的遺失,跟這件事多常發生,是兩回事。

重切原始碼

FMS

FMS/__init__.py
FMS/architecture.json
{
  "name": "011-cpython-shelve",
  "upstream": "CPython Lib/shelve.py",
  "examined_version": "3.14.5",
  "license": "PSF-2.0",
  "what_it_is": "A dict-like object backed by a dbm file, whose single boolean flag decides whether a mutation through what it handed you means anything.",
  "why_this_one": "Example 011 the same day is the first in this lab with state that outlives the process, because the roadmap turns to real market applications at 20/20 and nothing here has been tested against persistence. shelve is the standard library's smallest persistent mapping, it is thirty years old, and its one flag changes the meaning of every read.",
  "declared_and_then_remeasured": {
    "_note": "Re-measured by main.py against the running interpreter. A disagreement is a failure. A file of measurements nobody re-reads is a declaration compared to nothing.",
    "shelve_py_lines": 250,
    "getitem_lines": 9,
    "setitem_lines": 7,
    "writeback_default": false,
    "public_classes": [
      "BsdDbShelf",
      "DbfilenameShelf",
      "Shelf"
    ],
    "_correction": "setitem_lines was declared 5 and measured 7 on the first run. Recorded rather than quietly overwritten: this row is the only evidence in the entry that the re-measurement can come out false."
  },
  "the_flag": {
    "name": "writeback",
    "what_it_is_called": "writeback",
    "what_it_actually_changes": [
      "whether a read RETAINS the object it just unpickled",
      "and therefore whether d[k] is d[k]",
      "and therefore whether a mutation through what you were handed reaches the medium at sync",
      "and therefore how much memory a session of pure reads costs"
    ],
    "the_gap": "The name describes the fourth consequence. The first is what causes all of them, and nothing in the API surfaces it."
  },
  "the_finding": "Two modes of one interface with opposite semantics for the same call. Under the default, d[k].append(x) is silently lost. Under writeback it survives. The observation that separates them is object identity - d[k] is d[k] - which no caller checks, and which costs one line.",
  "the_second_finding": "writeback turns a READ into a retention. 200 pure reads with no writes at all leave 200 objects held. The cache grows with what you have looked at, not with what you have changed, and nothing in the flag's name says so.",
  "sets": {
    "FMS": "this file: the flag, what it really changes, and the numbers main.py re-measures",
    "SCL": "which handout this deployment uses, and whether a declaration must be proved against behaviour",
    "SMS": "the re-cut Shelf, resolution by name, the identity probe, and the upstream probes",
    "TMS": "one file per handout strategy - each declares what it hands back and whether a mutation survives, and reaches no sibling set",
    "DMS": "the two modes side by side, the comparison against real shelve, and what none of it can see"
  },
  "non_goals": [
    "Saying writeback is a bug. It is off by default, documented, and correct for callers who want it.",
    "Reimplementing dbm. The re-cut takes the same backing mapping shelve.Shelf takes.",
    "Claiming the re-cut is better than upstream's arrangement. It is the same semantics with the strategy lifted out, which is worth exactly what the comparison against the real module says."
  ],
  "the_third_finding": "A read-only session under writeback rewrites the medium at close. Measured: open with writeback, read all 200 keys, write nothing, close - the store file changes. Under the default it does not. This row exists because the first version of that check was a hardcoded check(..., True, ...) asserting the read loop wrote nothing, which is the defect this lab filed against archaeology 008 on 2026-08-08. Measuring it disagreed with the assertion."
}

SCL

SCL/__init__.py
SCL/policy.json
{
  "handout": "copy-on-read",
  "declaration_must_match_behaviour": true,
  "recut_must_match_upstream": true,
  "_note": "main.py runs both handouts regardless of what this says. A policy able to silence the comparison would make the comparison worthless."
}
SCL/policy.py
"""Which handout this deployment uses, and what it refuses to let pass."""
import json
import pathlib

_C = json.loads((pathlib.Path(__file__).parent / "policy.json").read_text(encoding="utf-8"))

handout = lambda: _C["handout"]                                                  # noqa: E731
declaration_must_match_behaviour = lambda: bool(_C["declaration_must_match_behaviour"])  # noqa: E731
recut_must_match_upstream = lambda: bool(_C["recut_must_match_upstream"])        # noqa: E731

SMS

SMS/__init__.py
SMS/shelf.py
"""The re-cut: a shelf whose handout strategy is a named unit rather than a flag.

Upstream the choice is a boolean threaded through `__getitem__`, `__setitem__`
and `sync`. Lifting it out is the only structural change; the semantics are
copied, and DMS compares the re-cut against real `shelve` on every run so that
"copied" is a measurement rather than a claim.
"""
import importlib
import pickle

HANDOUTS = ["copy_on_read", "cached_reference"]


def load_handouts():
    loaded, problems = {}, []
    for module_name in HANDOUTS:
        try:
            module = importlib.import_module(f"TMS.handouts.{module_name}")
        except ModuleNotFoundError:
            problems.append(f'handout "{module_name}" has no module - fail closed')
            continue
        for attribute in ("NAME", "HANDS_BACK", "MUTATION_SURVIVES", "make"):
            if not hasattr(module, attribute):
                problems.append(f"{module_name} does not declare {attribute}")
        loaded[module.NAME] = module
    return loaded, problems


def resolve(name, loaded):
    module = loaded.get(name)
    if module is None:
        known = ", ".join(sorted(loaded))
        return None, f'handout "{name}" has no implementation - fail closed (known: {known})'
    return module, None


class Shelf:
    """Same backing mapping shelve.Shelf takes: keys to pickled bytes."""

    def __init__(self, backing, handout):
        self.backing = backing
        self.handout_name = handout.NAME
        self.policy = handout.make(pickle.loads)

    def __setitem__(self, key, value):
        self.backing[key.encode()] = pickle.dumps(value)
        self.policy["remember"](key, value)

    def __getitem__(self, key):
        return self.policy["answer"](key, self.backing[key.encode()])

    def sync(self):
        # Upstream writes the cache back here. The re-cut does the same, and
        # this is the line that makes a mutation through a handed-out object
        # reach the medium at all.
        for key, value in self.policy["items"]():
            self.backing[key.encode()] = pickle.dumps(value)

    def held(self):
        return self.policy["held"]()

    def keys(self):
        return sorted(k.decode() for k in self.backing)


def hands_back_copies(shelf, key):
    """The observation that separates the strategies, and the only cheap one."""
    return shelf[key] is not shelf[key]


def mutation_survives(shelf, key, mutate):
    """The other one. It only fires if the caller thought to mutate."""
    mutate(shelf[key])
    return shelf[key]
SMS/upstream.py
"""What real shelve does, measured — not what its documentation says it does.

The re-cut in shelf.py is compared against these results cell by cell, so
"the re-cut copies upstream's semantics" is a measurement that can come out
false.
"""
import hashlib
import inspect
import os
import shelve
import tempfile


def _store():
    return os.path.join(tempfile.mkdtemp(), "store")


def probe(writeback):
    """Write, mutate through what a read handed back, reopen, see what survived."""
    path = _store()
    with shelve.open(path, writeback=writeback) as shelf:
        shelf["cart"] = ["apple"]

    with shelve.open(path, writeback=writeback) as shelf:
        shelf["cart"].append("pear")
        identity_separates = shelf["cart"] is not shelf["cart"]
        held = len(getattr(shelf, "cache", {}))

    with shelve.open(path) as shelf:
        survived = list(shelf["cart"])

    return {
        "survived": survived,
        "mutation_survives": survived == ["apple", "pear"],
        "identity_separates": identity_separates,
        "held": held,
    }


def cache_after_pure_reads(count):
    """Reads only. Nothing is written, and the cache grows anyway."""
    path = _store()
    with shelve.open(path, writeback=True) as shelf:
        for index in range(count):
            shelf[f"k{index}"] = [index]
    with shelve.open(path, writeback=True) as shelf:
        marks = {}
        for index in range(count):
            shelf[f"k{index}"]
            if index + 1 in (1, count // 4, count):
                marks[index + 1] = len(shelf.cache)
    return marks


def reads_cause_writes(count, writeback):
    """Open, read every key, close. Did the medium change?

    This replaces a hardcoded `check(..., True, ...)` that asserted the read
    loop wrote nothing. Asserting it was the same defect this lab filed against
    itself on 2026-08-08, and measuring it gives a different answer.
    """
    directory = tempfile.mkdtemp()
    path = os.path.join(directory, "store")
    with shelve.open(path, writeback=True) as shelf:
        for index in range(count):
            shelf[f"k{index}"] = [index]

    def fingerprint():
        return {name: hashlib.sha256(
            open(os.path.join(directory, name), "rb").read()).hexdigest()[:12]
            for name in sorted(os.listdir(directory))}

    before = fingerprint()
    with shelve.open(path, writeback=writeback) as shelf:
        for index in range(count):
            shelf[f"k{index}"]
    after = fingerprint()

    changed = sorted(name for name in before if before.get(name) != after.get(name))
    return {"files": len(before), "changed": changed, "unchanged": len(before) - len(changed)}


def returns_nothing_discriminating():
    """The BP-0004 family: which operations answer the same thing however they went."""
    path = _store()
    with shelve.open(path) as shelf:
        return {
            "__setitem__ (wrote)": shelf.__setitem__("a", [1]),
            "sync() (nothing cached)": shelf.sync(),
            "get('missing')": shelf.get("missing"),
            "get('a') is a live ref": shelf.get("a") is shelf.get("a"),
        }


def structure():
    source = inspect.getsource(shelve)
    return {
        "shelve_py_lines": len(source.splitlines()),
        "getitem_lines": len(inspect.getsource(shelve.Shelf.__getitem__).splitlines()),
        "setitem_lines": len(inspect.getsource(shelve.Shelf.__setitem__).splitlines()),
        "writeback_default": inspect.signature(shelve.open).parameters["writeback"].default,
        "public_classes": sorted(
            name for name, value in vars(shelve).items()
            if isinstance(value, type) and not name.startswith("_")
            and value.__module__ == "shelve"),
    }

TMS

TMS/__init__.py
TMS/handouts/__init__.py
TMS/handouts/cached_reference.py
"""Unpickle once, then hand the same object back forever.

Upstream this is `writeback=True`. Two things follow that the flag's name does
not say: a mutation through what you were handed is visible to later readers
and is written out at sync; and a pure READ retains the object, so the cache
grows with what you have looked at rather than with what you have changed.
"""
NAME = "cached-reference"
HANDS_BACK = "the same object every read, retained in this process"
MUTATION_SURVIVES = True


def make(deserialise):
    cache = {}

    def answer(key, serialised):
        if key not in cache:
            cache[key] = deserialise(serialised)
        return cache[key]

    def remember(key, value):
        cache[key] = value

    def held():
        return len(cache)

    def items():
        return list(cache.items())

    return {"answer": answer, "remember": remember, "held": held, "items": items}
TMS/handouts/copy_on_read.py
"""Unpickle on every read. What the caller gets is theirs.

Upstream this is `writeback=False`, the default, and it is three lines of
`Shelf.__getitem__` that never touch the cache.
"""
NAME = "copy-on-read"
HANDS_BACK = "a fresh object on every read"
MUTATION_SURVIVES = False


def make(deserialise):
    def answer(key, serialised):
        return deserialise(serialised)

    def remember(key, value):
        return None

    def held():
        return 0

    def items():
        # Nothing is retained, so a sync has nothing to write back. That is the
        # whole reason a mutation through a handed-out object goes nowhere.
        return []

    return {"answer": answer, "remember": remember, "held": held, "items": items}

DMS

DMS/__init__.py
DMS/report.py
"""The two modes side by side, the comparison, and the gaps."""


def modes(rows, out):
    out(f"\n  {'writeback':<12} {'d[k].append(x) survives':<26} {'d[k] is d[k]':<14} objects held")
    for row in rows:
        out(f"  {str(row['writeback']):<12} {str(row['survived']):<26} "
            f"{str(not row['identity_separates']):<14} {row['held']}")


def growth(marks, out):
    out("\n  reads only, nothing written:")
    for read, held in sorted(marks.items()):
        out(f"    after reading {read:>4} keys, the cache holds {held}")


def nothing_discriminating(values, out):
    out("\n  operations whose answer is the same however they went:")
    for label, value in values.items():
        out(f"    {label:<26} {value!r}")


def comparison(disagreements, cells, out):
    if disagreements:
        for line in disagreements:
            out(f"    DISAGREES  {line}")
    else:
        out(f"    {cells} of {cells} cells agree - the lifted strategy decides what "
            f"the flag decided")


def gaps(out):
    out("\n  measurable, not measured here:")
    out("    - how often real code mutates what a shelf handed it")
    out("    - what the retained objects cost on a session-sized workload")
    out("\n  not measurable by this entry at all:")
    out("    - whether the default is wrong. It is off, it is documented, and")
    out("      turning it on costs memory that most callers do not want to spend.")
    out("    - whether anyone has been bitten in production. Reproducing a silent")
    out("      loss says nothing about how often it happens.")

root

island_test.py
"""The island test, and the drills that let each comparison come out false.

    python src/island_test.py

Section 3 compares the re-cut against the shelve running right now. Section 3b
breaks the re-cut on purpose so that comparison is a measurement rather than a
formality, and section 2b mislabels a handout so the declaration check is too.
"""
import pathlib
import pickle
import re
import sys

HERE = pathlib.Path(__file__).parent
sys.path.insert(0, str(HERE))

from SCL import policy  # noqa: E402
from SMS import shelf, upstream  # noqa: E402

FAILURES = []


def check(label, ok, detail=""):
    print(f"  {'PASS' if ok else 'FAIL'}  {label}{' - ' + detail if detail else ''}")
    if not ok:
        FAILURES.append(label)


LOADED, PROBLEMS = shelf.load_handouts()


def through_recut(module):
    backing = {}
    store = shelf.Shelf(backing, module)
    store["cart"] = ["apple"]
    reopened = shelf.Shelf(backing, module)
    reopened["cart"].append("pear")
    separates = shelf.hands_back_copies(reopened, "cart")
    held = reopened.held()
    reopened.sync()
    survived = pickle.loads(backing[b"cart"])
    return {"mutation_survives": survived == ["apple", "pear"],
            "identity_separates": separates, "held": held}


print("\n== 1. every handout is an island and declares what it hands back")
check("both handouts loaded with no problems", not PROBLEMS, "; ".join(PROBLEMS))
handout_dir = HERE / "TMS" / "handouts"
files = sorted(f for f in handout_dir.iterdir() if f.suffix == ".py" and f.name != "__init__.py")
check("there are two handout files", len(files) == 2, ", ".join(f.stem for f in files))
for f in files:
    reaches = re.findall(r"^\s*(?:from|import)\s+(\S+)", f.read_text(encoding="utf-8"), re.M)
    siblings = [r for r in reaches if r.split(".")[0] in {"TMS", "SMS", "SCL", "DMS", "FMS"}]
    check(f"{f.stem} reaches no sibling set", not siblings,
          ", ".join(reaches) or "no imports at all")
for name, module in sorted(LOADED.items()):
    check(f"{name} says what it hands back", bool(module.HANDS_BACK), module.HANDS_BACK)

print("\n== 2. the declaration is checked by running it, not by reading it")
for name, module in sorted(LOADED.items()):
    measured = through_recut(module)
    check(f"{name}: declared mutation_survives={module.MUTATION_SURVIVES}, measured "
          f"{measured['mutation_survives']}",
          measured["mutation_survives"] == module.MUTATION_SURVIVES)

print("\n== 2b. the drill: a handout that lies about itself must be caught")


class Mislabelled:
    NAME = "mislabelled"
    HANDS_BACK = "a fresh object on every read"
    MUTATION_SURVIVES = False          # the lie
    make = staticmethod(LOADED["cached-reference"].make)   # the behaviour


measured = through_recut(Mislabelled)
check("a handout declaring copy semantics while caching is caught",
      measured["mutation_survives"] != Mislabelled.MUTATION_SURVIVES,
      f"declared {Mislabelled.MUTATION_SURVIVES}, measured {measured['mutation_survives']}")

print("\n== 3. the re-cut against the shelve running right now")
CELLS = []
for writeback, handout_name in ((False, "copy-on-read"), (True, "cached-reference")):
    measured = upstream.probe(writeback)
    modelled = through_recut(LOADED[handout_name])
    for field in ("mutation_survives", "identity_separates"):
        CELLS.append({"writeback": writeback, "field": field,
                      "upstream": measured[field], "recut": modelled[field]})
agree = [c for c in CELLS if c["upstream"] == c["recut"]]
check(f"all {len(CELLS)} cells agree", len(agree) == len(CELLS),
      f"{len(agree)}/{len(CELLS)}")

print("\n== 3b. the drill: can that comparison come out false?")


class Swapped:
    NAME = "swapped"
    HANDS_BACK = "wrong on purpose"
    MUTATION_SURVIVES = False
    make = staticmethod(LOADED["cached-reference"].make)


broken = through_recut(Swapped)
against_default = upstream.probe(False)
check("using the wrong strategy for writeback=False breaks cells",
      any(broken[f] != against_default[f] for f in ("mutation_survives", "identity_separates")),
      "so section 3 is a measurement, not a formality")

print("\n== 4. the flag is named for its fourth consequence")
marks = upstream.cache_after_pure_reads(200)
check("200 pure reads retain 200 objects", marks.get(200) == 200,
      ", ".join(f"{k} reads -> {v} held" for k, v in sorted(marks.items())))
# The previous version of this line was `check(..., True, ...)` - an assertion
# that the read loop wrote nothing. That is the hardcoded-True defect this lab
# filed against archaeology 008 on 2026-08-08, and measuring it disagrees.
under_writeback = upstream.reads_cause_writes(200, writeback=True)
under_default = upstream.reads_cause_writes(200, writeback=False)
check("a READ-ONLY session under writeback rewrites the medium at close",
      bool(under_writeback["changed"]),
      f"{len(under_writeback['changed'])} of {under_writeback['files']} files changed: "
      f"{', '.join(under_writeback['changed'])}")
check("the same read-only session under the default does not",
      not under_default["changed"],
      f"{under_default['unchanged']} of {under_default['files']} files unchanged")
check("so the two differ, which is what makes either mean anything",
      bool(under_writeback["changed"]) != bool(under_default["changed"]))

print("\n== 5. what answers the same however it went")
values = upstream.returns_nothing_discriminating()
same = [label for label, value in values.items() if value is None]
check("three operations return None on every path", len(same) == 3, ", ".join(same))
check("and the one observation that does discriminate is identity",
      values["get('a') is a live ref"] is False,
      "under the default, two reads of one key are two objects")

print("\n== 6. fail closed")
_, problem = shelf.resolve("write-through", LOADED)
check("an unresolvable handout stops the run", problem is not None, problem or "resolved anyway")
check("SCL names a handout that exists", policy.handout() in LOADED, policy.handout())

print("\n== 7. what this entry cannot see")
print("        MEASURABLE, NOT MEASURED")
print("          - how often real code mutates what a shelf handed it")
print("          - what the retained objects cost on a session-sized workload")
print("        NOT MEASURABLE HERE")
print("          - whether the default is wrong. It is off, documented, and turning")
print("            it on costs memory most callers do not want to spend.")
print("          - frequency in the wild. Reproducing a silent loss says nothing")
print("            about how often anyone meets it.")

print(f"\n{len(FAILURES)} failure(s)" if FAILURES else "\nall checks passed")
for f in FAILURES:
    print(f"  - {f}")
sys.exit(1 if FAILURES else 0)
main.py
"""CPython's shelve, re-cut so the handout strategy is a unit rather than a flag.

    python src/main.py            the two modes, the growth, and the comparison
    python src/main.py --strict   exit 1 if the re-cut disagrees with real shelve
"""
import json
import pathlib
import pickle
import sys

HERE = pathlib.Path(__file__).parent
sys.path.insert(0, str(HERE))

from DMS import report  # noqa: E402
from SCL import policy  # noqa: E402
from SMS import shelf, upstream  # noqa: E402

ARCH = json.loads((HERE / "FMS" / "architecture.json").read_text(encoding="utf-8"))
BY_WRITEBACK = {False: "copy-on-read", True: "cached-reference"}


def recut(handout_name, loaded):
    """The same three operations the upstream probe performs, through the re-cut."""
    module, problem = shelf.resolve(handout_name, loaded)
    if problem:
        return None, problem
    backing = {}
    store = shelf.Shelf(backing, module)
    store["cart"] = ["apple"]

    store2 = shelf.Shelf(backing, module)
    store2["cart"].append("pear")
    identity_separates = shelf.hands_back_copies(store2, "cart")
    held = store2.held()
    store2.sync()

    survived = pickle.loads(backing[b"cart"])
    return {"survived": survived, "mutation_survives": survived == ["apple", "pear"],
            "identity_separates": identity_separates, "held": held}, None


def main(argv):
    out = lambda line="": sys.stdout.write(line + "\n")  # noqa: E731
    loaded, problems = shelf.load_handouts()
    if problems:
        for problem in problems:
            out(f"  !! {problem}")
        return 1

    out(f"\n== one interface, two meanings for the same call  "
        f"[shelve.py {ARCH['examined_version']}]")
    rows, disagreements = [], []
    for writeback, handout_name in BY_WRITEBACK.items():
        measured = upstream.probe(writeback)
        rows.append({"writeback": writeback, **measured})

        modelled, problem = recut(handout_name, loaded)
        if problem:
            out(f"  !! {problem}")
            return 1
        for field in ("mutation_survives", "identity_separates"):
            if modelled[field] != measured[field]:
                disagreements.append(
                    f"writeback={writeback}/{field}: re-cut {modelled[field]}, "
                    f"shelve {measured[field]}")
    report.modes(rows, out)

    out("\n== the flag is called writeback, and what it changes first is reads")
    report.growth(upstream.cache_after_pure_reads(200), out)

    report.nothing_discriminating(upstream.returns_nothing_discriminating(), out)

    out("\n== the re-cut against the shelve that is running right now")
    report.comparison(disagreements, len(BY_WRITEBACK) * 2, out)

    out("\n== what each handout declares, and what it did")
    for handout_name in sorted(loaded):
        module = loaded[handout_name]
        modelled, _ = recut(handout_name, loaded)
        agrees = modelled["mutation_survives"] == module.MUTATION_SURVIVES
        out(f"    {'ok ' if agrees else 'NO '} {module.NAME:<18} says {module.HANDS_BACK}")
        out(f"    {'':4} {'':<18} mutation survives: declared "
            f"{module.MUTATION_SURVIVES}, measured {modelled['mutation_survives']}")

    out("\n== the numbers FMS declares, re-measured")
    declared, measured = ARCH["declared_and_then_remeasured"], upstream.structure()
    wrong = []
    for key, value in measured.items():
        agrees = declared.get(key) == value
        if not agrees:
            wrong.append(f"{key}: declared {declared.get(key)!r}, measured {value!r}")
        out(f"    {'ok ' if agrees else 'NO '} {key:<22} {value}")

    report.gaps(out)

    if "--strict" in argv and (wrong or (disagreements and policy.recut_must_match_upstream())):
        for line in wrong:
            out(f"\n  !! {line}")
        return 1
    return 0


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))