pymarc 5.2.0__tar.gz → 5.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pymarc-5.2.0/pymarc.egg-info → pymarc-5.2.2}/PKG-INFO +1 -1
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/field.py +24 -15
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/record.py +1 -1
- {pymarc-5.2.0 → pymarc-5.2.2/pymarc.egg-info}/PKG-INFO +1 -1
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc.egg-info/SOURCES.txt +0 -1
- {pymarc-5.2.0 → pymarc-5.2.2}/setup.py +1 -1
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_field.py +9 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_record.py +2 -0
- pymarc-5.2.0/release-notes.md +0 -129
- {pymarc-5.2.0 → pymarc-5.2.2}/CONTRIBUTING.md +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/LICENSE +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/MANIFEST.in +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/README.md +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/README_pt_Br.md +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/docs/source/conf.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/docs/source/index.rst +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/__init__.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/constants.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/exceptions.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/leader.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/marc8.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/marc8_mapping.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/marcjson.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/marcxml.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/py.typed +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/reader.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc/writer.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc.egg-info/dependency_links.txt +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/pymarc.egg-info/top_level.txt +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/requirements.dev.txt +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/setup.cfg +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/1251.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/__init__.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/alphatag.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/bad_eacc_encoding.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/bad_indicator.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/bad_marc8_escape.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/bad_records.mrc +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/bad_subfield_code.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/bad_tag.xml +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/batch.json +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/batch.xml +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/diacritic.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/marc.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/marc8-to-unicode.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/marc8.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/multi_isbn.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/one.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/one.json +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/regression45.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test.json +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_encode.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_json.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_leader.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_marc8.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_marc8.txt +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_ordered_fields.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_reader.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_utf8.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_utf8.txt +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_writer.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/test_xml.py +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/testunimarc.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/utf8.xml +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/utf8_errors.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/utf8_invalid.mrc +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/utf8_with_leader_flag.dat +0 -0
- {pymarc-5.2.0 → pymarc-5.2.2}/test/utf8_without_leader_flag.dat +0 -0
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"""The pymarc field file."""
|
|
8
8
|
import logging
|
|
9
9
|
from collections import defaultdict
|
|
10
|
-
from typing import List, Optional, DefaultDict, NamedTuple, Iterator, Dict
|
|
10
|
+
from typing import List, Optional, DefaultDict, NamedTuple, Iterator, Dict, Sequence
|
|
11
11
|
|
|
12
12
|
from pymarc.constants import SUBFIELD_INDICATOR, END_OF_FIELD
|
|
13
13
|
from pymarc.marc8 import marc8_to_unicode
|
|
@@ -44,7 +44,7 @@ class Field:
|
|
|
44
44
|
field = Field(tag='001', data='fol05731351')
|
|
45
45
|
"""
|
|
46
46
|
|
|
47
|
-
__slots__ = ("tag", "data", "
|
|
47
|
+
__slots__ = ("tag", "data", "_indicators", "subfields", "__pos", "control_field")
|
|
48
48
|
|
|
49
49
|
def __init__(
|
|
50
50
|
self,
|
|
@@ -67,20 +67,8 @@ class Field:
|
|
|
67
67
|
"""
|
|
68
68
|
)
|
|
69
69
|
|
|
70
|
-
if (
|
|
71
|
-
indicators
|
|
72
|
-
and isinstance(indicators, (list, tuple))
|
|
73
|
-
and len(indicators) != 2
|
|
74
|
-
):
|
|
75
|
-
raise ValueError(
|
|
76
|
-
"""The indicators input no longer accepts an iterable of arbitrary length. Use
|
|
77
|
-
the Indicators() named tuple instead. Please consult the documentation
|
|
78
|
-
for details.
|
|
79
|
-
"""
|
|
80
|
-
)
|
|
81
|
-
|
|
82
70
|
self.subfields: List[Subfield] = []
|
|
83
|
-
self.
|
|
71
|
+
self._indicators: Optional[Indicators] = None
|
|
84
72
|
self.data: Optional[str] = None
|
|
85
73
|
self.control_field: bool = False
|
|
86
74
|
|
|
@@ -101,6 +89,27 @@ class Field:
|
|
|
101
89
|
else:
|
|
102
90
|
self.indicators = indicators
|
|
103
91
|
|
|
92
|
+
@property
|
|
93
|
+
def indicators(self) -> Optional[Indicators]:
|
|
94
|
+
"""Return the field's indicators."""
|
|
95
|
+
return self._indicators
|
|
96
|
+
|
|
97
|
+
@indicators.setter
|
|
98
|
+
def indicators(self, value: Sequence) -> None:
|
|
99
|
+
"""Set the field's indicators."""
|
|
100
|
+
if value and isinstance(value, (list, tuple)) and len(value) != 2:
|
|
101
|
+
raise ValueError(
|
|
102
|
+
"""The indicators input no longer accepts an iterable of arbitrary length. Use
|
|
103
|
+
the Indicators() named tuple instead. Please consult the documentation
|
|
104
|
+
for details.
|
|
105
|
+
"""
|
|
106
|
+
)
|
|
107
|
+
if value is not None:
|
|
108
|
+
if isinstance(value, Indicators):
|
|
109
|
+
self._indicators = value
|
|
110
|
+
else:
|
|
111
|
+
self._indicators = Indicators(*value)
|
|
112
|
+
|
|
104
113
|
@classmethod
|
|
105
114
|
def convert_legacy_subfields(cls, subfields: List[str]) -> List[Subfield]:
|
|
106
115
|
"""
|
|
@@ -105,7 +105,7 @@ class Record:
|
|
|
105
105
|
encoding=file_encoding,
|
|
106
106
|
)
|
|
107
107
|
elif force_utf8:
|
|
108
|
-
self.leader = self.leader[0:9] + "a" + self.leader[10:]
|
|
108
|
+
self.leader = Leader(self.leader[0:9] + "a" + self.leader[10:])
|
|
109
109
|
|
|
110
110
|
def __str__(self) -> str:
|
|
111
111
|
"""Will return a prettified version of the record in MARCMaker format.
|
|
@@ -132,6 +132,15 @@ class FieldTest(unittest.TestCase):
|
|
|
132
132
|
self.assertEqual(self.field.indicator2, "1")
|
|
133
133
|
self.assertEqual(self.field.indicators.second, "1")
|
|
134
134
|
|
|
135
|
+
def test_reassign_indicators(self):
|
|
136
|
+
self.field.indicators = (" ", "1")
|
|
137
|
+
self.assertEqual(self.field.indicator1, " ")
|
|
138
|
+
self.assertEqual(self.field.indicator2, "1")
|
|
139
|
+
|
|
140
|
+
self.field.indicators = ["1", " "]
|
|
141
|
+
self.assertEqual(self.field.indicator1, "1")
|
|
142
|
+
self.assertEqual(self.field.indicator2, " ")
|
|
143
|
+
|
|
135
144
|
def test_subfields_created(self):
|
|
136
145
|
subfields = self.field.subfields
|
|
137
146
|
self.assertEqual(len(subfields), 2)
|
|
@@ -14,6 +14,7 @@ from pymarc.exceptions import (
|
|
|
14
14
|
from pymarc.field import Field, Subfield, Indicators
|
|
15
15
|
from pymarc.reader import MARCReader
|
|
16
16
|
from pymarc.record import Record
|
|
17
|
+
from pymarc.leader import Leader
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
class RecordTest(unittest.TestCase):
|
|
@@ -724,6 +725,7 @@ class RecordTest(unittest.TestCase):
|
|
|
724
725
|
subfields=[Subfield(code="a", value="The pragmatic programmer")],
|
|
725
726
|
)
|
|
726
727
|
)
|
|
728
|
+
self.assertTrue(isinstance(record.leader, Leader))
|
|
727
729
|
transmission_format = record.as_marc()
|
|
728
730
|
transmission_format_leader = transmission_format[0:24]
|
|
729
731
|
self.assertEqual(transmission_format_leader, b"00067 a2200037 4500")
|
pymarc-5.2.0/release-notes.md
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
Generate release notes for the following git commit log messages.
|
|
2
|
-
|
|
3
|
-
commit aab33190d5f5633d5e835bf0baa4469687afa783
|
|
4
|
-
Author: Jeremy Nelson <jermnelson@gmail.com>
|
|
5
|
-
Date: Thu May 9 12:20:22 2024 -0700
|
|
6
|
-
|
|
7
|
-
For MARC readers, initialize Leader class instead of string, which will make accessing and updating the MARC leader easier, and less error prone -- from @jermnelson
|
|
8
|
-
|
|
9
|
-
Test coverage on GitLab merge requests -- from @herrboyer
|
|
10
|
-
|
|
11
|
-
Adding MARCMakerReader for generating MARC data with textual format, previously pymarc only could generate records in this format -- from @herrboyer
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
commit d7ad0062c599642584b3035d8c8d0d9ea0746043
|
|
15
|
-
Author: Renaud Boyer <rboyer@anybox.fr>
|
|
16
|
-
Date: Mon May 6 19:16:18 2024 +0200
|
|
17
|
-
|
|
18
|
-
MARCMakerReader
|
|
19
|
-
|
|
20
|
-
This commit adds a new class pymarc.str.MARCMakerReader for reading MARC records
|
|
21
|
-
that are encoded using the MARCMaker format. Previously pymarc only had
|
|
22
|
-
the ability to *write* records in this format.
|
|
23
|
-
|
|
24
|
-
MARCMaker is human readable version of a MARC record, for example:
|
|
25
|
-
|
|
26
|
-
```text
|
|
27
|
-
=LDR 01060cam 22002894a 4500
|
|
28
|
-
=001 11778504
|
|
29
|
-
=008 990802s2000\\\\mau\\\\\\b\\\\001\0\eng\\
|
|
30
|
-
=050 00$aQA76.6$b.H857 2000
|
|
31
|
-
=100 1\$aHunt, Andrew,$d1964-
|
|
32
|
-
=245 14$aThe pragmatic programmer :$bfrom journeyman to master /$cAndrew Hunt, David Thomas.
|
|
33
|
-
=260 \\$aReading, Mass :$bAddison-Wesley,$c2000.
|
|
34
|
-
=300 \\$axxiv, 321 p. ;$c24 cm.
|
|
35
|
-
=504 \\$aIncludes bibliographical references.
|
|
36
|
-
=650 \0$aComputer programming.
|
|
37
|
-
=700 1\$aThomas, David,$d1956-
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
In order to read it you instantiate a MARCMakerReader object and use it
|
|
41
|
-
as an iterator. For example, to get the first record:
|
|
42
|
-
|
|
43
|
-
```python
|
|
44
|
-
from pymarc import MARCMakerReader
|
|
45
|
-
|
|
46
|
-
rec = next(MARCMakerReader(open('record.mkr')))
|
|
47
|
-
print(rec.title)
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
It works similarl to MARCReader, but you don't open the file in binary
|
|
51
|
-
mode, since it's assume to be a UTF-8 encoded string. You can change the
|
|
52
|
-
encoding with the `encoding` parameter.
|
|
53
|
-
|
|
54
|
-
:100644 100644 7472b52 d00fffd M docs/source/index.rst
|
|
55
|
-
:100644 100644 fd652eb 1e25af3 M pymarc/reader.py
|
|
56
|
-
:100644 100644 224214a c1abf6e M setup.cfg
|
|
57
|
-
:100644 100644 d54a5a9 7f6ab4e M test/test_reader.py
|
|
58
|
-
|
|
59
|
-
commit ea843bfb177f6b8cdd7990976febda39a43545f6
|
|
60
|
-
Author: Andrew Hankinson <andrew.hankinson@gmail.com>
|
|
61
|
-
Date: Sat May 4 18:54:11 2024 +0000
|
|
62
|
-
|
|
63
|
-
Create Indicators type
|
|
64
|
-
|
|
65
|
-
Previously, indicators of any length could be supplied with no checks on their length. This change introduces an "Indicators" named tuple that can only have two positions. If an iterable (list or tuple) of not exactly length two is passed, then a ValueError is now raised.
|
|
66
|
-
|
|
67
|
-
The "old style" where a list of two elements are passed is still handled in the constructor; however, the type hints will indicate that this is not correct. (This is in preference to raising a Deprecation message). Internally this is coerced to the new named tuple type.
|
|
68
|
-
|
|
69
|
-
If no indicator is passed, the value will be an indicator tuple with two space characters. As far as I can tell this was the default behaviour of pymarc previously.
|
|
70
|
-
|
|
71
|
-
Tests are also updated to work with the new Indicator types, with tests for the old behaviour also added.
|
|
72
|
-
|
|
73
|
-
Fixes #195
|
|
74
|
-
|
|
75
|
-
:100644 100644 38644ae 02b6213 M .gitlab-ci.yml
|
|
76
|
-
:100644 100644 2b7e616 7ebc97c M README.md
|
|
77
|
-
:100644 100644 82538e1 7fc524f M README_pt_Br.md
|
|
78
|
-
:100644 100644 0982fc7 7472b52 M docs/source/index.rst
|
|
79
|
-
:100644 100644 f9972f5 d554b58 M pymarc/field.py
|
|
80
|
-
:100644 100644 4055ee8 776e447 M pymarc/marc8.py
|
|
81
|
-
:100644 100644 fbb3445 2e6babc M pymarc/marcjson.py
|
|
82
|
-
:100644 100644 e27ddce 2b72ae8 M pymarc/marcxml.py
|
|
83
|
-
:100644 100644 fdd42ef fd652eb M pymarc/reader.py
|
|
84
|
-
:100644 100644 83b880b ac9368f M pymarc/record.py
|
|
85
|
-
:100644 100644 c5270fe 1c70b47 M test/test_field.py
|
|
86
|
-
:100644 100644 5e62063 46c4b62 M test/test_json.py
|
|
87
|
-
:100644 100644 a451151 348dcca M test/test_marc8.py
|
|
88
|
-
:100644 100644 8260f81 e5d4e37 M test/test_ordered_fields.py
|
|
89
|
-
:100644 100644 a123183 932e864 M test/test_record.py
|
|
90
|
-
:100644 100644 45122cc a9684cf M test/test_writer.py
|
|
91
|
-
|
|
92
|
-
commit 4ea33e9b2f50e0000d8a59f1aa175b7c9611fbef
|
|
93
|
-
Author: Andrew Hankinson <andrew.hankinson@gmail.com>
|
|
94
|
-
Date: Tue Mar 26 18:04:17 2024 +0100
|
|
95
|
-
|
|
96
|
-
Fixed: Raise KeyError for setitem
|
|
97
|
-
|
|
98
|
-
To match __getitem__, __setitem__ now raises a KeyError for setting subfields on control fields.
|
|
99
|
-
|
|
100
|
-
:100644 100644 60e3596 f9972f5 M pymarc/field.py
|
|
101
|
-
|
|
102
|
-
commit 6f88fc411d4890e399bcfa6378b75de3dc1e5606
|
|
103
|
-
Author: Andrew Hankinson <andrew.hankinson@gmail.com>
|
|
104
|
-
Date: Tue Mar 26 15:35:23 2024 +0100
|
|
105
|
-
|
|
106
|
-
Fixed: Iterating over fields fails
|
|
107
|
-
|
|
108
|
-
Previously, iterating over fields and calling 'field.code' on the list of fields might fail, if the field was a control field.
|
|
109
|
-
|
|
110
|
-
This was because `self.subfields` was only initialized if the field was not a control field, so it was attempting to iterate over an undefined property. For any blind iteration of all fields in a record, and all subfields in those fields, this raised an exception.
|
|
111
|
-
|
|
112
|
-
To fix this, all fields are now pre-initialized in the init method, and updated with their value depending on the field status as a control field. Iterating over the subfields of a control field will no longer crash, but the list of subfields will be empty. Similarly, the `data` property is initialized to `None`, so accessing non-control fields' data property will also not crash.
|
|
113
|
-
|
|
114
|
-
Additionally, the `is_control_field()` method has been refactored, and now takes its value from the `control_field` property set on initialization. This is because the nature of the field is set at init, so no need to re-check it.
|
|
115
|
-
|
|
116
|
-
:100644 100644 277701e 60e3596 M pymarc/field.py
|
|
117
|
-
:100644 100644 f19c844 fbb3445 M pymarc/marcjson.py
|
|
118
|
-
:100644 100644 8a4ca3b e27ddce M pymarc/marcxml.py
|
|
119
|
-
:100644 100644 e6d6bdc 83b880b M pymarc/record.py
|
|
120
|
-
:100644 100644 cf5e8d4 c5270fe M test/test_field.py
|
|
121
|
-
:100644 100644 865cdab 8cab292 M test/test_xml.py
|
|
122
|
-
|
|
123
|
-
commit 5265ccb48b75424dfadd9c79e7788ae554f7b8b9
|
|
124
|
-
Author: Benjamin Webb <bwebb@gpo.gov>
|
|
125
|
-
Date: Fri Mar 22 09:46:37 2024 -0400
|
|
126
|
-
|
|
127
|
-
Updated property name in docstrings
|
|
128
|
-
|
|
129
|
-
:100644 100644 2fc1d13 d01b429 M pymarc/leader.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|