You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Record.get(tag) for pymarc compatibility: Dict-like record.get('245') returns the first matching field or a default value, mirroring pymarc's Record.get(). Delegates to existing get_field().
Field.is_control_field() and ControlField.is_control_field() for pymarc compatibility: Returns False on data fields and True on control fields, matching pymarc's unified Field.is_control_field() API.
Record.__str__ and Record.__repr__: The Python Record wrapper now delegates to the Rust implementation instead of showing the default <mrrc.Record object at 0x...>. str(rec) returns Record(type=a) and repr(rec) returns <Record type=a fields=N>.
SubfieldPatternQuery negation flag (#63, #73): SubfieldPatternQuery("020", "a", r"^978-", negate=True) pushes pattern inversion into Rust so non-matching fields never cross the FFI boundary. Thanks to @acdha@code4lib.social for suggesting this.
SubfieldValueQuery negation flag (#64, #74): SubfieldValueQuery("650", "a", "History", negate=True) pushes value inversion into Rust. Works with both exact and partial matching.
Comprehensive pymarc API compatibility (#71, #72): Full drop-in replacement for pymarc. Thanks to @mistersql@mastodon.social for highlighting several of these compatibility gaps. Changes include:
Record accessors as @property: All 17 record accessors (title, author, isbn, issn, subjects, location, notes, publisher, uniform_title, sudoc, issn_title, issnl, pubyear, series, physical_description, plus aliases physicaldescription, uniformtitle, addedentries) are now properties, matching pymarc's record.title syntax.
Unified ControlField into Field: Field('001', data='12345') creates a control field. ControlField remains as a backward-compatible subclass. Control field content accessed via .data attribute.
Record['xxx'] raises KeyError for missing tags (use record.get(tag) for safe access), matching pymarc behavior.
Record.as_marc() / as_marc21(): Returns ISO 2709 bytes.
MARC constants: LEADER_LEN, DIRECTORY_ENTRY_LEN, END_OF_FIELD, END_OF_RECORD, SUBFIELD_INDICATOR, MARC_XML_NS, MARC_XML_SCHEMA.
Exception hierarchy: MrrcException base class with RecordLengthInvalid, RecordLeaderInvalid, BaseAddressInvalid, BaseAddressNotFound, RecordDirectoryInvalid, EndOfRecordNotFound, FieldNotFound, FatalReaderError, and BadSubfieldCodeWarning.
pubyear returns str (not int), matching pymarc.
Breaking Changes
Record accessors are now @property: record.title() → record.title. Affects all 17 accessors: title, author, isbn, issn, issn_title, issnl, subjects, notes, location, series, sudoc, publisher, pubyear, physical_description, uniform_title, plus new physicaldescription, uniformtitle, addedentries.
pubyear returns str: Previously returned Optional[int], now returns Optional[str] to match pymarc.
Record['xxx'] raises KeyError for missing tags: Previously returned None. Use record.get(tag) for safe access that returns None.
ControlField unified into Field: ControlField is now a subclass of Field. Control field content is in .data (not .value). Field('001', data='12345') is the preferred constructor.
remove_field() returns None: Previously returned a list of removed fields.
add_field() / remove_field() accept *args: Signature changed from single field to *fields. Existing single-arg calls still work.
Default Field indicators changed from '0' to ' ': Matches pymarc. Only affects fields created without explicit indicators.
Changed
SubfieldPatternQuery and SubfieldValueQuery marked #[non_exhaustive] (#74): Prevents external struct literal construction, requiring use of constructors. Future field additions will not be semver-breaking.
mrrc.__version__ now reports the correct version: Previously hardcoded as "0.1.0" in both mrrc/__init__.py and src-python/src/lib.rs. Now derived from Cargo.toml at compile time via env!("CARGO_PKG_VERSION"), eliminating the need to manually update version strings during releases.
Documentation
Migration guide updated: Added record.get() and field.is_control_field() examples to docs/guides/migration-from-pymarc.md, reflecting closer pymarc API parity.
All docs and examples updated for pymarc API compatibility: Record accessors now shown as properties (record.title not record.title()), control field access uses .data, missing-field access patterns use record.get() or try/except, and new methods/constants/exceptions are documented throughout the API reference, migration guide, quickstart, tutorials, and runnable examples.