import pytest
from mrrc import MARCReader, Record, Field, Leader
import io
def create_field(tag, ind1=' ', ind2=' ', **subfields):
field = Field(tag, ind1, ind2)
for code, value in subfields.items():
field.add_subfield(code, value)
return field
class TestRecordAddField:
def test_add_field(self):
record = Record()
field = Field('245', '1', '0')
field.add_subfield('a', 'Python')
field.add_subfield('c', 'Guido')
record.add_field(field)
assert field in record.fields()
class TestRecordFields:
def test_fields_access(self):
record = Record()
field1 = Field('245', '1', '0')
field1.add_subfield('a', 'Python')
field1.add_subfield('c', 'Guido')
record.add_field(field1)
field2 = Field('260', ' ', ' ')
field2.add_subfield('a', 'Amsterdam')
record.add_field(field2)
assert record['245'] is not None
assert record['245']['a'] == 'Python'
assert record['260']['a'] == 'Amsterdam'
class TestRecordRemoveField:
def test_remove_existing_field(self):
record = Record()
field = Field('245', '1', '0')
field.add_subfield('a', 'Python')
field.add_subfield('c', 'Guido')
record.add_field(field)
assert record['245']['a'] == 'Python'
record.remove_field(field)
assert record.get_field('245') is None
class TestRecordQuickAccess:
def test_quick_access_syntax(self):
record = Record()
title = Field('245', '1', '0')
title.add_subfield('a', 'Python')
title.add_subfield('c', 'Guido')
record.add_field(title)
assert record['245'] == title
assert record.get_field('999') is None
class TestRecordMembership:
def test_in_operator(self):
record = Record()
title = Field('245', '1', '0')
title.add_subfield('a', 'Python')
record.add_field(title)
assert '245' in record
assert '999' not in record
class TestRecordFind:
def test_get_fields_by_tag(self):
record = Record()
subject1 = Field('650', ' ', '0')
subject1.add_subfield('a', 'Programming Language')
record.add_field(subject1)
subject2 = Field('650', ' ', '0')
subject2.add_subfield('a', 'Object Oriented')
record.add_field(subject2)
found = record.get_fields('650')
assert len(found) == 2
assert found[0].subfields_by_code('a')[0] == 'Programming Language'
assert found[1].subfields_by_code('a')[0] == 'Object Oriented'
found_all = record.get_fields()
assert len(found_all) == 2
class TestRecordMultiFind:
def test_get_fields_multiple_tags(self):
record = Record()
subject1 = Field('650', ' ', '0')
subject1.add_subfield('a', 'Programming Language')
record.add_field(subject1)
subject2 = Field('651', ' ', '0')
subject2.add_subfield('a', 'Object Oriented')
record.add_field(subject2)
found = record.get_fields('650', '651')
assert len(found) == 2
class TestRecordFieldNotFound:
def test_empty_record_fields(self):
record = Record()
assert len(record.fields()) == 0
class TestRecordAuthor:
def test_author_from_100_field(self):
record = Record()
assert record.author is None
record.add_field(create_field('100', '1', ' ',
a='Bletch, Foobie,',
d='1979-1981.'))
assert record.author is not None
assert 'Bletch' in record.author
class TestRecordUniformTitle:
def test_uniform_title_from_130_field(self):
record = Record()
assert record.uniform_title is None
record.add_field(create_field('130', '0', ' ',
a='Tosefta.',
l='English.',
f='1977.'))
uniform_title = record.uniform_title
assert uniform_title is not None
class TestRecordSubjects:
def test_subjects_from_650_fields(self):
record = Record()
record.add_field(create_field('650', ' ', '0', a='Computer science'))
record.add_field(create_field('650', ' ', '0', a='Python language'))
subjects = record.subjects
assert len(subjects) >= 2
assert any('Computer' in s for s in subjects)
def test_subjects_from_all_6xx_fields(self):
record = Record()
record.add_field(create_field('600', '1', '0', a='Maimonides, Moses,'))
record.add_field(create_field('610', '2', '0', a='United Nations'))
record.add_field(create_field('611', '2', '0', a='Vatican Council'))
record.add_field(create_field('630', '0', '4', a='Talmud Bavli.'))
record.add_field(create_field('648', ' ', '0', a='20th century'))
record.add_field(create_field('650', ' ', '0', a='Jewish law.'))
record.add_field(create_field('651', ' ', '0', a='Jerusalem'))
record.add_field(create_field('655', ' ', '7', a='Commentaries.'))
subjects = record.subjects
assert len(subjects) == 8
assert 'Maimonides, Moses,' in subjects
assert 'United Nations' in subjects
assert 'Vatican Council' in subjects
assert 'Talmud Bavli.' in subjects
assert '20th century' in subjects
assert 'Jewish law.' in subjects
assert 'Jerusalem' in subjects
assert 'Commentaries.' in subjects
class TestRecordPublisher:
def test_publisher_from_260_field(self):
record = Record()
assert record.publisher is None
record.add_field(create_field('260', ' ', ' ',
a='Paris :',
b='Gauthier-Villars ;',
c='1955.'))
assert record.publisher is not None
assert 'Villars' in record.publisher
def test_publisher_from_264_rda_field(self):
record = Record()
record.add_field(create_field('264', ' ', '1',
a='Cambridge, Massachusetts :',
b='The MIT Press,',
c='[2022]'))
assert record.publisher == 'The MIT Press,'
def test_publisher_prefers_260_over_264(self):
record = Record()
record.add_field(create_field('260', ' ', ' ',
b='Old Publisher,'))
record.add_field(create_field('264', ' ', '1',
b='New Publisher,'))
assert record.publisher == 'Old Publisher,'
def test_publisher_ignores_264_non_publication(self):
record = Record()
record.add_field(create_field('264', ' ', '3',
b='Some Printer,'))
assert record.publisher is None
class TestRecordPublicationYear:
def test_publication_year_from_260_field(self):
record = Record()
assert record.pubyear is None
record.add_field(create_field('260', ' ', ' ',
a='Paris :',
b='Gauthier-Villars ;',
c='1955.'))
year = record.pubyear
assert year is not None
def test_publication_year_from_264_rda_field(self):
record = Record()
record.add_field(create_field('264', ' ', '1',
c='[2022]'))
assert record.pubyear == '2022'
class TestRecordISBN:
def test_isbn_from_020_field(self):
record = Record()
assert record.isbn is None
record.add_field(create_field('020', ' ', ' ', a='0914378287'))
assert record.isbn is not None
class TestRecordISSN:
def test_issn_from_022_field(self):
record = Record()
assert record.issn is None
record.add_field(create_field('022', ' ', ' ', a='0028-0836'))
issn = record.issn
assert issn is not None
assert '0028-0836' in issn
class TestRecordTitle:
def test_title_from_245_field(self):
record = Record()
assert record.title is None
record.add_field(create_field('245', '1', '0', a='Python Programming'))
title = record.title
assert title is not None
assert 'Python' in title
class TestRecordAsMarc:
def test_as_marc_serialization(self):
record = Record()
record.add_field(create_field('245', '0', '1', a='The pragmatic programmer'))
marc_bytes = record.to_marc21()
assert isinstance(marc_bytes, bytes)
assert len(marc_bytes) > 0
assert len(marc_bytes) >= 24
class TestRecordAsJsonXml:
def test_as_json_format(self):
record = Record()
record.add_field(create_field('245', '1', '0', a='Title'))
json_str = record.to_json()
assert json_str is not None
assert isinstance(json_str, str)
def test_as_xml_format(self):
record = Record()
record.add_field(create_field('245', '1', '0', a='Title'))
xml_str = record.to_xml()
assert xml_str is not None
assert isinstance(xml_str, str)
assert '<' in xml_str
class TestRecordPhysicalDescription:
def test_physical_description(self):
record = Record()
assert record.physical_description is None
record.add_field(create_field('300', ' ', ' ',
a='1 photographic print :',
b='gelatin silver ;',
c='10 x 56 in.'))
desc = record.physical_description
assert desc is not None
class TestRecordLocation:
def test_location_field(self):
record = Record()
assert record.location == []
record.add_field(create_field('852', ' ', ' ',
a='Main Library',
b='Reference'))
locs = record.location
assert len(locs) >= 1
class TestRecordNotes:
def test_notes_field(self):
record = Record()
assert record.notes == []
record.add_field(create_field('500', ' ', ' ',
a='This is a general note.'))
notes = record.notes
assert len(notes) >= 1
class TestMARCReaderBasic:
def test_reader_iteration(self, fixture_1k):
data = io.BytesIO(fixture_1k)
reader = MARCReader(data)
count = 0
for record in reader:
if record:
count += 1
if count >= 5:
break
assert count > 0
class TestMARCReaderRecordCount:
def test_reader_count(self, fixture_1k):
data = io.BytesIO(fixture_1k)
reader = MARCReader(data)
count = 0
for record in reader:
if record:
count += 1
assert count > 0
class TestFieldCreation:
def test_field_with_subfields(self):
field = Field('245', '1', '0')
field.add_subfield('a', 'The pragmatic programmer :')
field.add_subfield('b', 'from journeyman to master /')
assert field.tag == '245'
assert len(field.subfields()) == 2
def test_field_indicators(self):
field = Field('245', '1', '0')
assert field.indicator1 == '1'
assert field.indicator2 == '0'
class TestFieldSubfieldAccess:
def test_subfield_by_code(self):
field = Field('245', '1', '0')
field.add_subfield('a', 'Main title')
field.add_subfield('b', 'Subtitle')
a_values = field.subfields_by_code('a')
assert len(a_values) == 1
assert a_values[0] == 'Main title'
def test_get_subfields_multiple_codes(self):
field = Field('260', ' ', ' ')
field.add_subfield('a', 'New York')
field.add_subfield('b', 'Publisher')
field.add_subfield('c', '2023')
values = field.get_subfields('a', 'b')
assert 'New York' in values
assert 'Publisher' in values
class TestLeaderBasics:
def test_leader_creation(self):
leader = Leader()
assert leader.record_type == 'a'
assert leader.bibliographic_level == 'm'
assert leader.record_status == 'n'
def test_leader_properties(self):
leader = Leader()
leader.record_type = 'c'
assert leader.record_type == 'c'
leader.bibliographic_level = 'd'
assert leader.bibliographic_level == 'd'
class TestRoundTripSerialization:
def test_record_roundtrip(self):
original = Record()
original.add_control_field('001', 'original-id-001')
original.add_field(create_field('245', '1', '0', a='Test Title'))
original.add_field(create_field('100', '1', ' ', a='Test Author'))
marc_bytes = original.to_marc21()
reader = MARCReader(io.BytesIO(marc_bytes))
restored = reader.read_record()
assert restored is not None
assert restored.title is not None
assert restored.author is not None
class TestMultipleFormats:
def test_json_roundtrip_concept(self):
record = Record()
record.add_field(create_field('245', '1', '0', a='Title'))
json_str = record.to_json()
assert isinstance(json_str, str)
assert len(json_str) > 0
def test_xml_serialization(self):
record = Record()
record.add_field(create_field('245', '1', '0', a='Title'))
xml_str = record.to_xml()
assert isinstance(xml_str, str)
assert len(xml_str) > 0
if __name__ == '__main__':
pytest.main([__file__, '-v'])