from __future__ import annotations
import io
from pathlib import Path
import pytest
import mrrc
_REPO_ROOT = Path(__file__).resolve().parents[2]
_VALID = _REPO_ROOT / "tests" / "data" / "simple_book.mrc"
_TOTAL = 100
_MALFORMED_EVERY = (
10 )
def _build_corpus() -> tuple[bytes, list[bool]]:
valid = _VALID.read_bytes()
malformed = bytearray(valid)
for i in range(24, 36):
malformed[i] = ord("X")
malformed = bytes(malformed)
records: list[bytes] = []
expected: list[bool] = []
for i in range(_TOTAL):
is_malformed = i % _MALFORMED_EVERY == (_MALFORMED_EVERY - 1)
records.append(malformed if is_malformed else valid)
expected.append(not is_malformed)
return b"".join(records), expected
_FIXTURE_1K = _REPO_ROOT / "tests" / "data" / "fixtures" / "1k_records.mrc"
def _read_both(data: bytes):
pymarc = pytest.importorskip("pymarc")
mrrc_records = list(mrrc.MARCReader(data))
pymarc_records = list(pymarc.MARCReader(io.BytesIO(data)))
assert len(mrrc_records) == len(pymarc_records)
assert all(r is not None for r in mrrc_records)
assert all(r is not None for r in pymarc_records)
return mrrc_records, pymarc_records
def _assert_record_values_match(
mrrc_record, pymarc_record, where: str
) -> None:
assert str(mrrc_record.leader) == str(pymarc_record.leader), (
f"{where}: leader"
)
assert mrrc_record.title == pymarc_record.title, f"{where}: title"
mrrc_fields = mrrc_record.fields()
pymarc_fields = pymarc_record.fields
assert [f.tag for f in mrrc_fields] == [f.tag for f in pymarc_fields], (
f"{where}: field tag sequence"
)
for mrrc_field, pymarc_field in zip(
mrrc_fields, pymarc_fields, strict=False
):
tag = mrrc_field.tag
assert mrrc_field.format_field() == pymarc_field.format_field(), (
f"{where} field {tag}: format_field()"
)
assert mrrc_field.value() == pymarc_field.value(), (
f"{where} field {tag}: value()"
)
assert mrrc_record.as_marc() == pymarc_record.as_marc(), (
f"{where}: as_marc() bytes"
)
def test_value_level_parity_simple_book() -> None:
mrrc_records, pymarc_records = _read_both(_VALID.read_bytes())
_assert_record_values_match(
mrrc_records[0], pymarc_records[0], "simple_book"
)
def test_value_level_parity_1k_corpus() -> None:
if not _FIXTURE_1K.exists():
pytest.skip(f"Fixture not found: {_FIXTURE_1K}")
mrrc_records, pymarc_records = _read_both(_FIXTURE_1K.read_bytes())
for i, (mrrc_record, pymarc_record) in enumerate(
zip(mrrc_records, pymarc_records, strict=False)
):
_assert_record_values_match(mrrc_record, pymarc_record, f"record {i}")
def test_permissive_iteration_shape_matches_pymarc() -> None:
pymarc = pytest.importorskip("pymarc")
stream, expected = _build_corpus()
mrrc_shape = [
r is not None for r in mrrc.MARCReader(stream, permissive=True)
]
pymarc_shape = [
r is not None
for r in pymarc.MARCReader(io.BytesIO(stream), permissive=True)
]
assert len(mrrc_shape) == _TOTAL, (
f"mrrc iterated {len(mrrc_shape)}, expected {_TOTAL}"
)
assert len(pymarc_shape) == _TOTAL, (
f"pymarc iterated {len(pymarc_shape)}, expected {_TOTAL}"
)
assert mrrc_shape == expected, (
"mrrc shape diverged from the corpus pattern"
)
assert pymarc_shape == expected, (
"pymarc shape diverged from the corpus pattern"
)
assert mrrc_shape == pymarc_shape