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

007 — CPython json 3.14.5:身分測試早就在跑,而答案取決於你問哪一種相同

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

python src/main.py          # 兩個實作 vs 一份寫下來的等價契約
python src/island_test.py   # 24 項檢查,其中 9 項直接量 CPython 本體

為什麼選它

今天的範例 007 把 MSSP 的身分測試變成可執行的:把宣稱是 SMS 的模組換成 stub,跑,問答案還在不在。結論比我預期的小——機械化能檢查的是結構與宣稱用途之間的一致性,不是成員資格,因為換一個「答案是什麼」的寫法,名冊就變了。

那個結論需要一個不是我發明的案例來檢驗。json 是理想的:它有一個 C 加速器 _json,跟一份純 Python 後備,而整個模組的結構就是為了「這東西可以不在」

# json/scanner.py
try:
    from _json import make_scanner as c_make_scanner
except ImportError:
    c_make_scanner = None
make_scanner = c_make_scanner or py_make_scanner

上游二十年來一直在對 _json 跑身分測試——只是那個測試的形式是一個執行期後備,不是一份報告。

原專案的結構地圖

檔案 行數
json/__init__.py 365
json/decoder.py 364
json/encoder.py 461
json/scanner.py 73

加速器是 _json,一個內建 C 模組。三個檔案裡有 16 處引用 C 版本,每一處都是同一個形狀:try: from _json import X except ImportError: X = None,然後 use = c_X or py_X

scanner.py 只有 73 行,而它是整個選擇發生的地方。

MSSP 重切

先講量到什麼,因為那才是重點。

_json 跑身分測試

  values are byte-identical with and without the accelerator  — 12 strings compared
  every input is accepted or rejected the same way            — 12 of 12 same error class
  and exactly one error MESSAGE differs                       — '"\x"'
        C : Invalid \escape: line 1 column 2 (char 1)
        py: Invalid \escape: 'x': line 1 column 3 (char 2)

值完全相同。錯誤類別完全相同。訊息有一個不同——純 Python 的版本指名了那個非法的跳脫字元,而且欄位差一。

所以:

「加速器不是結構性的」在「同一個值」這個判準下為真,在「同一則訊息」這個判準下為偽。

同一份程式碼,兩個判準,兩個答案。 這正是範例 007 從我自己發明的程式裡得到的結論,而這裡是一份每個 Python 安裝都帶著、比那個發現早二十年的標準庫。

關掉它比看起來難,而我第一次量錯了

第一次的關法是 json.scanner.c_make_scanner = None沒有用

  clearing c_make_scanner alone does not switch the scanner - still _json

因為 make_scanner = c_make_scanner or py_make_scanner 在 import 時就跑完了,名字已經綁定。事後改掉 c_make_scanner 不影響任何已經綁好的東西。

我的第一次比較因此是 C 跟 C 自己比,然後回報「兩個實作完全相同」。那是一個通過而完全沒有碰到它宣稱的東西的檢查——BP-0005,抓到它的方法是去驗證驗證器:印出 type(decoder.scan_once).__module__,看到兩次都是 _json

正確的關法要重綁 make_scanner 本身。之後 _json -> builtins,比較才是真的。

重切改了兩件事

選擇是一個值,不是一個 import 時綁定的名字。 SMS/select.py 每次呼叫才選,而且回傳選了哪一個。上游做不到這件事不是疏忽:一行 or 在那個位置是正確的、便宜的、而且二十年沒出過問題。代價只在你想問「我剛才跑的是哪一個」或「這次請用另一個」的時候才出現。

等價是一份寫下來的契約,不是一個形容詞。 FMS/manifest.json

"equivalence_contract": {
  "must_be_identical": ["encoded output for every corpus value"],
  "may_differ": ["error message text"],
  "must_not_differ": ["the class of error raised", "whether an input is accepted at all"]
}

DMS/equivalence.py 逐條回答,而不是給一個 yes/no:

$ python src/main.py

  ok  encoded output identical for every value             7 identical, 0 differing
  ok  the class of error is the same                       2 same class, 0 differing
  ok  acceptance is the same                               0 input(s) one accepted and the other did not
  ok  error text identical  (contract says MAY differ)     2 message(s) differ

最後一列是重點:訊息確實不同,而契約說可以。把 SCL/policy.jsonerror_text_must_match 改成 true,同一次執行就會失敗。等價不是量出來的,是契約加上量測

main.py 還有一條上游不需要、而我需要的檢查:如果兩邊選到同一個實作,拒絕輸出等價結果。那是我第一次量 CPython 時缺的那條。

什麼不適合拆

try/except ImportError 那個模式不該被換成註冊表。 它一行、沒有狀態、在直譯器啟動的最早期就要能用,而 jsonlogginghttpurllib 都會拉進來的東西。一個需要初始化的選擇機制在這個位置是負債。

73 行的 scanner.py 不該再拆。 它只做一件事——把一個 decoder 變成一個 scan 函式——而那件事就是選擇本身。

_json 不該被拆進 decoder.py 它是 C,它的存在條件是「這個平台編得出來」,而那是一個部署事實,不是一個結構事實。上游把它放在一個可以不存在的位置是對的,本篇的重切只是把「它現在在不在」變成可以問的。

這次沒有解決什麼

改良點 8,每一項要說出把它變成量測需要多少。

重切原始碼

FMS

FMS/__init__.py
FMS/manifest.json
{
  "name": "json-accelerator-recut",
  "what_it_is": "A codec with an optional accelerator, where the choice is a value you can re-evaluate and the claim 'the accelerator is not structural' is a written contract the run checks.",
  "examined": {
    "project": "CPython json",
    "version": "3.14.5",
    "license": "PSF-2.0",
    "measured": {
      "json/__init__.py": 365,
      "json/decoder.py": 364,
      "json/encoder.py": 461,
      "json/scanner.py": 73,
      "accelerator": "_json, a built-in C module",
      "selection_shape": "make_scanner = c_make_scanner or py_make_scanner, evaluated at import time"
    },
    "identity_test_run_on_upstream": {
      "values": "21 of 21 encode/decode results byte-identical with and without _json",
      "errors": "1 of 13 error messages differs",
      "the_one": "'\\x' -> C: Invalid \\escape: line 1 column 2 (char 1) / py: Invalid \\escape: 'x': line 1 column 3 (char 2)"
    }
  },
  "the_finding": "CPython already runs the identity test on _json, as a runtime fallback: the module structures itself so the accelerator can be absent. Under the witness 'same value', the accelerator is not structural. Under the witness 'same error message', it is observable. Same code, two witnesses, two answers — which is example 007's finding, confirmed on stdlib code that predates it by two decades.",
  "the_second_finding": "Turning the accelerator off is harder than it looks. `make_scanner = c_make_scanner or py_make_scanner` runs at import time, so setting c_make_scanner = None afterwards changes nothing that has already been bound. My first comparison ran C against C and reported the two implementations identical.",
  "equivalence_contract": {
    "must_be_identical": ["encoded output for every corpus value"],
    "may_differ": ["error message text"],
    "must_not_differ": ["the class of error raised", "whether an input is accepted at all"]
  },
  "sets": {
    "FMS": "this file, including the equivalence contract",
    "SCL": "whether this deployment may use the accelerator at all",
    "SMS": "selection and the equivalence runner's driver",
    "TMS": "two implementations of the same escaper, each importing nothing",
    "DMS": "what the two implementations agreed and disagreed about, by contract clause"
  },
  "non_goals": [
    "Being a JSON library. One escaper, no parser.",
    "Claiming CPython's divergence is a bug. It is a message, the contract permits it, and this entry's point is that the contract has to be written down before that sentence means anything."
  ]
}

SCL

SCL/__init__.py
SCL/policy.json
{
  "policy_version": "1.0",
  "_comment": [
    "A deployment may refuse the accelerator - for reproducibility across hosts,",
    "or because it is auditing the pure implementation. Upstream has no such",
    "switch: the choice is made at import time by what is installed."
  ],
  "accelerator": "allow",
  "error_text_must_match": false
}
SCL/policy.py
"""What this deployment permits."""
import json
import pathlib

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


def accelerator_allowed():
    return _C["accelerator"] == "allow"


def error_text_must_match():
    return bool(_C["error_text_must_match"])

SMS

SMS/__init__.py
SMS/drive.py
"""Run one corpus through one implementation and collect what happened."""


def run(module, corpus):
    values, errors = [], []
    for item in corpus:
        try:
            values.append(module.escape(item))
            errors.append(None)
        except Exception as exc:  # noqa: BLE001 - the class IS the observation
            values.append(None)
            errors.append((type(exc).__name__, str(exc)))
    return values, errors
SMS/select.py
"""Choosing an implementation, and being able to say which one you got.

Upstream binds the choice at import time:

    make_scanner = c_make_scanner or py_make_scanner    # json/scanner.py

That is one line, it is correct, and it has a consequence: after import there is
no way to select the other one, and no way to ask which was taken except by
inspecting the type of an object it produced. Setting c_make_scanner = None
later changes nothing, because the `or` already ran.

Here the choice is made per call from values that are still live, and the
selection is returned beside the result.
"""
import importlib

FAST = "impl/fast"
PLAIN = "impl/plain"


def available():
    """Which implementations this installation actually has."""
    found = []
    for name in (FAST, PLAIN):
        try:
            importlib.import_module(f"TMS.{name.replace('/', '.')}")
            found.append(name)
        except ImportError:
            pass
    return found


def choose(prefer_fast, allowed):
    """Return (name, module). Never raises for a missing accelerator."""
    order = [FAST, PLAIN] if (prefer_fast and allowed) else [PLAIN]
    for name in order:
        try:
            return name, importlib.import_module(f"TMS.{name.replace('/', '.')}")
        except ImportError:
            continue
    raise RuntimeError("no implementation is available at all")

TMS

TMS/__init__.py
TMS/impl/__init__.py
TMS/impl/fast.py
"""The "accelerated" escaper: a table lookup built once.

Stands in for _json. Imports nothing.
"""

NAME = "impl/fast"

_TABLE = {c: f"\\u{ord(c):04x}" for c in map(chr, range(0x20))}
_TABLE.update({'"': '\\"', "\\": "\\\\", "\n": "\\n", "\t": "\\t", "\r": "\\r"})


def escape(text):
    if not isinstance(text, str):
        raise TypeError("escape expects str")
    return "".join(_TABLE.get(ch, ch) for ch in text)
TMS/impl/plain.py
"""The plain escaper: branches, no table.

Deliberately identical in output and DIFFERENT in one error message, which is
the divergence measured in CPython 3.14.5 between _json and its fallback.
Imports nothing.
"""

NAME = "impl/plain"

_NAMED = {'"': '\\"', "\\": "\\\\", "\n": "\\n", "\t": "\\t", "\r": "\\r"}


def escape(text):
    if not isinstance(text, str):
        # Upstream's fallback names the offending value; the C path does not.
        raise TypeError(f"escape expects str, got {type(text).__name__}")
    out = []
    for ch in text:
        if ch in _NAMED:
            out.append(_NAMED[ch])
        elif ord(ch) < 0x20:
            out.append(f"\\u{ord(ch):04x}")
        else:
            out.append(ch)
    return "".join(out)

DMS

DMS/__init__.py
DMS/equivalence.py
"""What the two implementations agreed and disagreed about, clause by clause.

The point is not "are they the same". It is "are they the same in the ways the
contract says they must be" — because 'the same' is not a property a machine can
check without being told which observations count.
"""


def compare(contract, corpus, a_name, a_result, b_name, b_result):
    a_values, a_errors = a_result
    b_values, b_errors = b_result
    findings = {"identical_values": 0, "differing_values": [], "same_error_class": 0,
                "differing_error_text": [], "differing_error_class": [], "acceptance_differs": []}

    for item, av, bv, ae, be in zip(corpus, a_values, b_values, a_errors, b_errors):
        label = repr(item)[:40]
        if (ae is None) != (be is None):
            findings["acceptance_differs"].append((label, a_name if ae is None else b_name))
            continue
        if ae is None:
            if av == bv:
                findings["identical_values"] += 1
            else:
                findings["differing_values"].append((label, av, bv))
            continue
        if ae[0] != be[0]:
            findings["differing_error_class"].append((label, ae[0], be[0]))
        else:
            findings["same_error_class"] += 1
            if ae[1] != be[1]:
                findings["differing_error_text"].append((label, ae[1], be[1]))
    return findings


def verdict(contract, findings, error_text_must_match):
    """Contract clauses, each answered by the run."""
    clauses = []
    clauses.append(("encoded output identical for every value",
                    not findings["differing_values"],
                    f"{findings['identical_values']} identical, {len(findings['differing_values'])} differing"))
    clauses.append(("the class of error is the same",
                    not findings["differing_error_class"],
                    f"{findings['same_error_class']} same class, {len(findings['differing_error_class'])} differing"))
    clauses.append(("acceptance is the same",
                    not findings["acceptance_differs"],
                    f"{len(findings['acceptance_differs'])} input(s) one accepted and the other did not"))
    # A waived pass must never render as a pass. The first version of this line
    # printed "ok" with "(contract says MAY differ)" appended, and a reader
    # skimming the column saw four greens over an observed difference. The
    # verdict WITHOUT the waiver is now shown beside the one with it, because
    # that is the only thing separating "a declared, temporary exception" from
    # "the system's identity was quietly rewritten".
    text_differs = bool(findings["differing_error_text"])
    unwaived = not text_differs
    waived = unwaived or not error_text_must_match
    label = "error text identical"
    if text_differs and waived:
        label += "  [WAIVED — would FAIL without the contract's may-differ]"
    elif not error_text_must_match:
        label += "  (contract says MAY differ; nothing used the waiver)"
    clauses.append((label, waived, f"{len(findings['differing_error_text'])} message(s) differ"))
    return clauses


def render(a_name, b_name, findings, clauses):
    lines = ["", f"== {a_name} vs {b_name}"]
    for label, ok, detail in clauses:
        lines.append(f"  {'ok ' if ok else '!! '} {label:<52} {detail}")
    if findings["differing_error_text"]:
        lines.append("")
        lines.append("  the observable difference, in full:")
        for label, a, b in findings["differing_error_text"]:
            lines.append(f"    input {label}")
            lines.append(f"      {a_name:<12} {a}")
            lines.append(f"      {b_name:<12} {b}")
    lines.append("")
    lines.append("  under 'same value' the accelerator is NOT structural.")
    lines.append("  under 'same message' it is observable. The contract is what decides.")
    return "\n".join(lines) + "\n"

root

island_test.py
"""The island test, and the live measurement of CPython's json accelerator.

    python src/island_test.py

Section 4 is the one that produced this entry: it turns _json off, proves the
switch actually happened, and then asks what changed.
"""
import importlib
import pathlib
import sys

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

from DMS import equivalence  # noqa: E402
from SCL import policy  # noqa: E402
from SMS import drive, select  # noqa: E402

FAILURES = []


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


print("\n== 1. each implementation is an island")
for name in ("fast", "plain"):
    module = importlib.import_module(f"TMS.impl.{name}")
    source = (HERE / "TMS" / "impl" / f"{name}.py").read_text(encoding="utf-8")
    report(f"impl/{name} escapes with no sibling loaded", module.escape('a"b') == 'a\\"b',
           module.escape('a"b'))
    report(f"impl/{name} imports nothing", "import " not in source)

print("\n== 2. the selection is a value, not a name bound at import time")
report("both implementations are available", len(select.available()) == 2,
       ", ".join(select.available()))
fast_name, _ = select.choose(prefer_fast=True, allowed=True)
plain_name, _ = select.choose(prefer_fast=False, allowed=True)
refused_name, _ = select.choose(prefer_fast=True, allowed=False)
report("preferring the accelerator selects it", fast_name == "impl/fast")
report("not preferring it selects the other", plain_name == "impl/plain")
report("SCL refusing it selects the other too", refused_name == "impl/plain",
       "upstream has no equivalent switch — the choice is made by what is installed")

print("\n== 3. the comparison refuses to compare something with itself")
{
}
findings = equivalence.compare(
    {}, ["x"], "impl/fast", drive.run(importlib.import_module("TMS.impl.fast"), ["x"]),
    "impl/fast", drive.run(importlib.import_module("TMS.impl.fast"), ["x"]))
report("comparing an implementation with itself finds no difference",
       findings["identical_values"] == 1 and not findings["differing_values"],
       "which is why main.py refuses to report it as an equivalence result")
main_source = (HERE / "main.py").read_text(encoding="utf-8")
report("and main.py has that refusal in code, not in prose",
       "REFUSING to report an equivalence" in main_source
       and "if fast_name == plain_name:" in main_source)

print("\n== 4. measured against CPython json 3.14.5 itself")
import json  # noqa: E402
import json.decoder  # noqa: E402
import json.encoder  # noqa: E402
import json.scanner  # noqa: E402

report("this interpreter is the examined version", sys.version.split()[0] == "3.14.5",
       sys.version.split()[0])
report("the C accelerator is present", importlib.util.find_spec("_json") is not None)

CORPUS = [{"a": 1, "b": [1, 2, {"c": None}]}, {"u": "héllo — 中文"}, [], {},
          {"n": [1.5, -0.0, 1e300]}, {"k": True, "l": None}]
BAD = ['{"a": }', '[1,]', '{"a" 1}', '"unterminated', '{1: 2}', '[1 2]', 'nul',
       '{"a": 1', '[', '1.', '"\\x"', '{"a": 01}']


def snapshot():
    decoder = json.decoder.JSONDecoder()
    encoder = json.encoder.JSONEncoder(sort_keys=True)
    values = [encoder.encode(obj) for obj in CORPUS]
    values += [repr(decoder.decode(encoder.encode(obj))) for obj in CORPUS]
    errors = []
    for text in BAD:
        try:
            decoder.decode(text)
            errors.append((text, None, "accepted"))
        except Exception as exc:  # noqa: BLE001
            errors.append((text, type(exc).__name__, str(exc)))
    return values, errors, type(decoder.scan_once).__module__


c_values, c_errors, c_scanner = snapshot()

# Setting c_make_scanner alone does NOT switch the decoder: json/scanner.py runs
# `make_scanner = c_make_scanner or py_make_scanner` at import time, so the name
# is already bound. My first measurement did exactly this and compared C with C.
json.scanner.c_make_scanner = None
_, _, still = snapshot()
report("clearing c_make_scanner alone does not switch the scanner", still == c_scanner,
       f"still {still} — the `or` already ran at import time")

json.scanner.make_scanner = json.scanner.py_make_scanner
json.encoder.c_make_encoder = None
json.decoder.scanstring = json.decoder.py_scanstring
json.encoder.encode_basestring_ascii = json.encoder.py_encode_basestring_ascii
json.encoder.encode_basestring = json.encoder.py_encode_basestring
py_values, py_errors, py_scanner = snapshot()

report("rebinding make_scanner does switch it", py_scanner != c_scanner,
       f"{c_scanner} -> {py_scanner}")
report("values are byte-identical with and without the accelerator",
       c_values == py_values, f"{len(c_values)} strings compared")

same_class = [c for c, p in zip(c_errors, py_errors) if c[1] == p[1]]
text_differs = [(c[0], c[2], p[2]) for c, p in zip(c_errors, py_errors) if c[1] == p[1] and c[2] != p[2]]
report("every input is accepted or rejected the same way",
       len(same_class) == len(BAD), f"{len(same_class)} of {len(BAD)} same error class")
report("and exactly one error MESSAGE differs", len(text_differs) == 1,
       "; ".join(f"{t!r}" for t, _, _ in text_differs))
for text, c, p in text_differs:
    print(f"        C : {c}")
    print(f"        py: {p}")
report("so 'the accelerator is not structural' is true only under a stated witness",
       c_values == py_values and len(text_differs) == 1,
       "same value: not structural. same message: observable.")

print("\n== 5. the checks can fail")
report("a comparison of two DIFFERENT implementations does find the difference",
       len(equivalence.compare({}, [42], "a", drive.run(importlib.import_module("TMS.impl.fast"), [42]),
                               "b", drive.run(importlib.import_module("TMS.impl.plain"), [42]))
           ["differing_error_text"]) == 1,
       "evaluated, not asserted")
report("the contract clause for error text can be made binding",
       any("MAY differ" not in label for label, _, _ in
           equivalence.verdict({}, {"differing_values": [], "identical_values": 0,
                                    "same_error_class": 0, "differing_error_class": [],
                                    "acceptance_differs": [], "differing_error_text": [("x", "a", "b")]},
                               True)),
       "policy.error_text_must_match() would turn today's pass into a failure")
report("this deployment does not require matching text", not policy.error_text_must_match())

print()
if FAILURES:
    print(f"  {len(FAILURES)} check(s) failed: {', '.join(FAILURES)}")
    raise SystemExit(1)
print("  island test passed")
main.py
"""Compare the two implementations against the written contract.

    python src/main.py
"""
import json
import pathlib
import sys

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

from DMS import equivalence  # noqa: E402
from SCL import policy  # noqa: E402
from SMS import drive, select  # noqa: E402

CORPUS = [
    "plain",
    'quote " and backslash \\',
    "tab\there",
    "newline\nhere",
    "control\x00\x1f",
    "unicode héllo 中文",
    "",
    42,          # not a str: both must raise
    None,        # not a str: both must raise
]


def main():
    manifest = json.loads(
        (pathlib.Path(__file__).parent / "FMS" / "manifest.json").read_text(encoding="utf-8"))
    contract = manifest["equivalence_contract"]

    print(f"\n  available implementations : {', '.join(select.available())}")
    print(f"  SCL allows the accelerator: {policy.accelerator_allowed()}")

    fast_name, fast = select.choose(prefer_fast=True, allowed=policy.accelerator_allowed())
    plain_name, plain = select.choose(prefer_fast=False, allowed=policy.accelerator_allowed())
    print(f"  chosen with preference    : {fast_name}")
    print(f"  chosen without            : {plain_name}")

    if fast_name == plain_name:
        print("\n  REFUSING to report an equivalence: both sides are the same implementation.")
        print("  This is the check my first measurement of CPython did not have, and it")
        print("  reported the C scanner identical to itself.")
        return 1

    findings = equivalence.compare(
        contract, CORPUS,
        fast_name, drive.run(fast, CORPUS),
        plain_name, drive.run(plain, CORPUS),
    )
    clauses = equivalence.verdict(contract, findings, policy.error_text_must_match())
    sys.stdout.write(equivalence.render(fast_name, plain_name, findings, clauses))
    return 0 if all(ok for _, ok, _ in clauses) else 2


if __name__ == "__main__":
    raise SystemExit(main())