pymarc 5.2.2__tar.gz → 5.2.3__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.3/.gitignore +20 -0
- pymarc-5.2.3/.gitlab-ci.yml +58 -0
- pymarc-5.2.3/.mailmap +7 -0
- pymarc-5.2.3/.readthedocs.yaml +22 -0
- {pymarc-5.2.2/pymarc.egg-info → pymarc-5.2.3}/PKG-INFO +118 -43
- {pymarc-5.2.2 → pymarc-5.2.3}/README.md +41 -24
- {pymarc-5.2.2 → pymarc-5.2.3}/README_pt_Br.md +1 -5
- pymarc-5.2.3/apply_headers.py +122 -0
- pymarc-5.2.3/docs/requirements.txt +1 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/docs/source/conf.py +0 -14
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/field.py +3 -1
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/record.py +4 -3
- pymarc-5.2.3/pyproject.toml +25 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/requirements.dev.txt +2 -1
- pymarc-5.2.3/setup.cfg +35 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_encode.py +0 -5
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_field.py +0 -5
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_json.py +0 -5
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_leader.py +0 -5
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_marc8.py +4 -5
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_ordered_fields.py +0 -5
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_reader.py +0 -11
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_record.py +0 -5
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_utf8.py +0 -5
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_writer.py +0 -9
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_xml.py +0 -5
- pymarc-5.2.2/PKG-INFO +0 -417
- pymarc-5.2.2/pymarc.egg-info/SOURCES.txt +0 -67
- pymarc-5.2.2/pymarc.egg-info/dependency_links.txt +0 -1
- pymarc-5.2.2/pymarc.egg-info/top_level.txt +0 -1
- pymarc-5.2.2/setup.cfg +0 -29
- pymarc-5.2.2/setup.py +0 -46
- {pymarc-5.2.2 → pymarc-5.2.3}/CONTRIBUTING.md +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/LICENSE +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/MANIFEST.in +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/docs/source/index.rst +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/__init__.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/constants.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/exceptions.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/leader.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/marc8.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/marc8_mapping.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/marcjson.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/marcxml.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/py.typed +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/reader.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/pymarc/writer.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/1251.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/__init__.py +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/alphatag.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/bad_eacc_encoding.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/bad_indicator.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/bad_marc8_escape.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/bad_records.mrc +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/bad_subfield_code.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/bad_tag.xml +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/batch.json +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/batch.xml +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/diacritic.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/marc.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/marc8-to-unicode.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/marc8.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/multi_isbn.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/one.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/one.json +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/regression45.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test.json +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_marc8.txt +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/test_utf8.txt +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/testunimarc.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/utf8.xml +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/utf8_errors.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/utf8_invalid.mrc +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/utf8_with_leader_flag.dat +0 -0
- {pymarc-5.2.2 → pymarc-5.2.3}/test/utf8_without_leader_flag.dat +0 -0
pymarc-5.2.3/.gitignore
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
stages:
|
|
2
|
+
- linting
|
|
3
|
+
- tests
|
|
4
|
+
|
|
5
|
+
default:
|
|
6
|
+
image: python:3.8-slim
|
|
7
|
+
|
|
8
|
+
# linting is only done once with default image
|
|
9
|
+
lint:
|
|
10
|
+
stage: linting
|
|
11
|
+
before_script:
|
|
12
|
+
- pip install uv
|
|
13
|
+
- uv venv
|
|
14
|
+
- uv sync
|
|
15
|
+
script:
|
|
16
|
+
- source .venv/bin/activate
|
|
17
|
+
- black --check --diff .
|
|
18
|
+
- flake8 .
|
|
19
|
+
- mypy --ignore-missing-imports .
|
|
20
|
+
|
|
21
|
+
# run tests and measure coverage with the default python version
|
|
22
|
+
test-coverage:
|
|
23
|
+
stage: tests
|
|
24
|
+
before_script:
|
|
25
|
+
- pip install uv
|
|
26
|
+
- uv venv
|
|
27
|
+
- uv sync
|
|
28
|
+
script:
|
|
29
|
+
- source .venv/bin/activate
|
|
30
|
+
- coverage run -m unittest discover
|
|
31
|
+
- coverage xml
|
|
32
|
+
- coverage report
|
|
33
|
+
# integrate coverage reports in GitLab
|
|
34
|
+
# see https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization.html
|
|
35
|
+
coverage: '/\d+\%\s*$/'
|
|
36
|
+
artifacts:
|
|
37
|
+
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}
|
|
38
|
+
reports:
|
|
39
|
+
coverage_report:
|
|
40
|
+
coverage_format: cobertura
|
|
41
|
+
path: coverage.xml
|
|
42
|
+
when: always
|
|
43
|
+
expire_in: 1 day
|
|
44
|
+
|
|
45
|
+
# run tests on other supported python versions
|
|
46
|
+
test-python:
|
|
47
|
+
stage: tests
|
|
48
|
+
parallel:
|
|
49
|
+
matrix:
|
|
50
|
+
- PYTHON_VERSION: ['3.9', '3.10', '3.11', '3.12', '3.13']
|
|
51
|
+
image: python:${PYTHON_VERSION}-slim
|
|
52
|
+
before_script:
|
|
53
|
+
- pip install uv
|
|
54
|
+
- uv venv
|
|
55
|
+
- uv sync
|
|
56
|
+
script:
|
|
57
|
+
- source .venv/bin/activate
|
|
58
|
+
- pytest
|
pymarc-5.2.3/.mailmap
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Aaron S. Lav <asl2@pobox.com>
|
|
2
|
+
Dan Scott <dan@coffeecode.net> <gitorious@coffeecode.net>
|
|
3
|
+
Eric Hellman <eric@hellman.net>
|
|
4
|
+
Edward Betts <edward@4angle.com> <edwardbetts@gmail.com>
|
|
5
|
+
James Tayson <james.taysom@gmail.com>
|
|
6
|
+
Nick Ruest <ruestn@gmail.com>
|
|
7
|
+
Geoffrey Spear <geoffspear@gmail.com> <speargh@pitt.edu>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# .readthedocs.yaml
|
|
2
|
+
# Read the Docs configuration file
|
|
3
|
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
4
|
+
|
|
5
|
+
# Required
|
|
6
|
+
version: 2
|
|
7
|
+
|
|
8
|
+
# Set the version of Python and other tools you might need
|
|
9
|
+
build:
|
|
10
|
+
os: ubuntu-22.04
|
|
11
|
+
tools:
|
|
12
|
+
python: "3.11"
|
|
13
|
+
|
|
14
|
+
# Build documentation in the docs/ directory with Sphinx
|
|
15
|
+
sphinx:
|
|
16
|
+
configuration: docs/source/conf.py
|
|
17
|
+
|
|
18
|
+
# Python requirements for the build
|
|
19
|
+
python:
|
|
20
|
+
install:
|
|
21
|
+
- requirements: docs/requirements.txt
|
|
22
|
+
|
|
@@ -1,25 +1,83 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: pymarc
|
|
3
|
-
Version: 5.2.
|
|
3
|
+
Version: 5.2.3
|
|
4
4
|
Summary: Read, write and modify MARC bibliographic data
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
5
|
+
License: Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
16
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
19
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
20
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
21
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
23
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
24
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
|
|
26
|
+
Copyright for this project is held by its many contributors, including:
|
|
27
|
+
|
|
28
|
+
Adam Constabaris <ajconsta@ncsu.edu>
|
|
29
|
+
Andrew Hankinson <andrew.hankinson@rism.digital>
|
|
30
|
+
André Nesse <an@macpro.lan>
|
|
31
|
+
Ben W <wrecksdart@gmail.com>
|
|
32
|
+
Chris Adams <chris@improbable.org>
|
|
33
|
+
Christian Clauss <cclauss@me.com>
|
|
34
|
+
Dan Chudnov <dchud@umich.edu>
|
|
35
|
+
Dan Davis <dan@danizen.net>
|
|
36
|
+
Dan Michael O. Heggø <danmichaelo@gmail.com>
|
|
37
|
+
Dan Scott <dan@coffeecode.net>
|
|
38
|
+
David Chouinard <david@davidchouinard.com>
|
|
39
|
+
Ed Hill <hill.charles2@gmail.com>
|
|
40
|
+
Ed Summers <ehs@pobox.com>
|
|
41
|
+
Edward Betts <edward@4angle.com>
|
|
42
|
+
Eric Hellman <eric@hellman.net>
|
|
43
|
+
Gabriel Farrell <gsf747@gmail.com>
|
|
44
|
+
Geoffrey Spear <geoffspear@gmail.com>
|
|
45
|
+
Godmar Back <godmar@gmail.com>
|
|
46
|
+
Harald Varner <harald.varner@gmail.com>
|
|
47
|
+
Helga <cdg013@gmail.com>
|
|
48
|
+
James Tayson <james.taysom@gmail.com>
|
|
49
|
+
Jay Luker <lbjay@reallywow.com>
|
|
50
|
+
Jeremy Nelson <jermnelson@gmail.com>
|
|
51
|
+
Jim Nicholls <jim.nicholls@gmail.com>
|
|
52
|
+
Jon Stroop <jpstroop@gmail.com>
|
|
53
|
+
Karol Sikora <me@karolsikora.me>
|
|
54
|
+
Lucas Souza <lucassouzaufpa@gmail.com>
|
|
55
|
+
María Matienzo <maria@matienzo.org>
|
|
56
|
+
Martin Czygan <martin.czygan@gmail.com>
|
|
57
|
+
Michael B. Klein <mbklein@gmail.com>
|
|
58
|
+
Michael J. Giarlo <leftwing@alumni.rutgers.edu>
|
|
59
|
+
Mikhail Terekhov <termim@gmail.com>
|
|
60
|
+
Nick Ruest <ruestn@gmail.com>
|
|
61
|
+
Pierre Verkest <pverkest@anybox.fr>
|
|
62
|
+
Radim Řehůřek <radimrehurek@seznam.cz>
|
|
63
|
+
Renaud Boyer <rboyer@anybox.fr>
|
|
64
|
+
Robert Marchman <robert.l.marchman@dartmouth.edu>
|
|
65
|
+
Sean Chen <schen@law.duke.edu>
|
|
66
|
+
Simon Hohl <simon.hohl@dainst.org>
|
|
67
|
+
Ted Lawless <tlawless@tuscola.(none)>
|
|
68
|
+
Theodor Tolstoy <gitlab.teddes@tolstoy.se>
|
|
69
|
+
Victor Seva <vseva@dlsi.ua.es>
|
|
70
|
+
Will Earp <will.earp@icloud.com>
|
|
71
|
+
cclauss <cclauss@bluewin.ch>
|
|
72
|
+
cyperus-papyrus <cdg013@gmail.com>
|
|
73
|
+
gitgovdoc <bwebb@gpo.gov>
|
|
74
|
+
klinga <klingaroo@gmail.com>
|
|
75
|
+
mmh <maherma@asdeguiaingenieria.com>
|
|
76
|
+
nemobis <federicoleva@tiscali.it>
|
|
77
|
+
wrCisco <lbjma@tiscali.it>
|
|
22
78
|
License-File: LICENSE
|
|
79
|
+
Requires-Python: >=3.8
|
|
80
|
+
Description-Content-Type: text/markdown
|
|
23
81
|
|
|
24
82
|
```
|
|
25
83
|
_|_|_| _| _| _|_|_| _|_| _|_|_| _| _|_| _|_|_|
|
|
@@ -47,26 +105,13 @@ pull request.
|
|
|
47
105
|
|
|
48
106
|
You can read pymarc documentation [here](https://pymarc.readthedocs.io/en/latest/).
|
|
49
107
|
|
|
50
|
-
|
|
108
|
+
## Installation
|
|
51
109
|
|
|
52
110
|
You'll probably just want to use pip to install pymarc:
|
|
53
111
|
|
|
54
112
|
pip install pymarc
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
git clone git://gitlab.com/pymarc/pymarc.git
|
|
59
|
-
|
|
60
|
-
You'll also need [setuptools](https://pypi.python.org/pypi/setuptools#installation-instructions). Once you have the source and setuptools run the pymarc test
|
|
61
|
-
suite to make sure things are in order with the distribution:
|
|
62
|
-
|
|
63
|
-
python setup.py test
|
|
64
|
-
|
|
65
|
-
And then install:
|
|
66
|
-
|
|
67
|
-
python setup.py install
|
|
68
|
-
|
|
69
|
-
### Reading
|
|
113
|
+
|
|
114
|
+
## Reading
|
|
70
115
|
|
|
71
116
|
Most often you will have some MARC data and will want to extract data
|
|
72
117
|
from it. Here's an example of reading a batch of records and printing out
|
|
@@ -133,7 +178,7 @@ MARC](http://www.loc.gov/marc/umb/) is a pretty good primer, and the [MARC 21
|
|
|
133
178
|
Formats](http://www.loc.gov/marc/marcdocz.html) page at the Library of Congress
|
|
134
179
|
is a good reference once you understand the basics.
|
|
135
180
|
|
|
136
|
-
|
|
181
|
+
## Writing
|
|
137
182
|
|
|
138
183
|
*Note: As of v5.0.0 `Subfield` is used to create subfields. Prior to v5,
|
|
139
184
|
subfields were constructed and accessed as a list of strings, e.g., `[code,
|
|
@@ -178,7 +223,7 @@ legacy_fields: list[str] = ['a', 'The pragmatic programmer : ',
|
|
|
178
223
|
coded_fields: list[Subfield] = Field.convert_legacy_subfields(legacy_fields)
|
|
179
224
|
```
|
|
180
225
|
|
|
181
|
-
|
|
226
|
+
## Updating
|
|
182
227
|
|
|
183
228
|
Updating works the same way, you read it in, modify it, and then write it out
|
|
184
229
|
again:
|
|
@@ -194,7 +239,7 @@ with open('file.dat', 'wb') as out:
|
|
|
194
239
|
```
|
|
195
240
|
|
|
196
241
|
|
|
197
|
-
|
|
242
|
+
## JSON and XML
|
|
198
243
|
|
|
199
244
|
If you find yourself using MARC data a fair bit, and distributing it, you may
|
|
200
245
|
make other developers a bit happier by using the JSON or XML serializations. The
|
|
@@ -402,8 +447,38 @@ print(records[0])
|
|
|
402
447
|
=700 1\$aCharles, Ray,$d1930-$4prf
|
|
403
448
|
```
|
|
404
449
|
|
|
405
|
-
|
|
406
|
-
|
|
450
|
+
## Developing
|
|
451
|
+
|
|
452
|
+
If you'd like to further develop pymarc you'll want to get the latest code:
|
|
453
|
+
|
|
454
|
+
git clone git://gitlab.com/pymarc/pymarc.git
|
|
455
|
+
cd pymarc
|
|
456
|
+
|
|
457
|
+
Create a virtual environment with [uv](https://docs.astral.sh/uv/) and activate it:
|
|
458
|
+
|
|
459
|
+
pip install uv
|
|
460
|
+
uv venv
|
|
461
|
+
uv sync
|
|
462
|
+
source .venv/bin/activate
|
|
463
|
+
|
|
464
|
+
Run the tests:
|
|
465
|
+
|
|
466
|
+
pytest
|
|
467
|
+
|
|
468
|
+
Run the lint tests:
|
|
469
|
+
|
|
470
|
+
flake8 .
|
|
471
|
+
|
|
472
|
+
And run type checking:
|
|
473
|
+
|
|
474
|
+
mypy --ignore-missing-imports .
|
|
475
|
+
|
|
476
|
+
If you want to build and publish a new version of pymarc on PyPI you can:
|
|
477
|
+
|
|
478
|
+
hatch build
|
|
479
|
+
hatch release
|
|
480
|
+
|
|
481
|
+
## Support
|
|
407
482
|
|
|
408
483
|
The pymarc developers encourage you to join the [pymarc Google
|
|
409
484
|
Group](http://groups.google.com/group/pymarc) if you need help. Also, please
|
|
@@ -412,6 +487,6 @@ GitLab to submit feature requests or bug reports. If you've got an itch to
|
|
|
412
487
|
scratch, please scratch it, and send merge requests on
|
|
413
488
|
[GitLab](http://gitlab.com/pymarc/pymarc).
|
|
414
489
|
|
|
415
|
-
If you start working with MARC you may feel like you need moral support
|
|
416
|
-
|
|
417
|
-
|
|
490
|
+
If you start working with MARC you may feel like you need moral support in
|
|
491
|
+
addition to technical support. The #python channel on [code4lib Slack]https://code4lib.org/slack/)
|
|
492
|
+
is a good place to start.
|
|
@@ -24,26 +24,13 @@ pull request.
|
|
|
24
24
|
|
|
25
25
|
You can read pymarc documentation [here](https://pymarc.readthedocs.io/en/latest/).
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
## Installation
|
|
28
28
|
|
|
29
29
|
You'll probably just want to use pip to install pymarc:
|
|
30
30
|
|
|
31
31
|
pip install pymarc
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
git clone git://gitlab.com/pymarc/pymarc.git
|
|
36
|
-
|
|
37
|
-
You'll also need [setuptools](https://pypi.python.org/pypi/setuptools#installation-instructions). Once you have the source and setuptools run the pymarc test
|
|
38
|
-
suite to make sure things are in order with the distribution:
|
|
39
|
-
|
|
40
|
-
python setup.py test
|
|
41
|
-
|
|
42
|
-
And then install:
|
|
43
|
-
|
|
44
|
-
python setup.py install
|
|
45
|
-
|
|
46
|
-
### Reading
|
|
32
|
+
|
|
33
|
+
## Reading
|
|
47
34
|
|
|
48
35
|
Most often you will have some MARC data and will want to extract data
|
|
49
36
|
from it. Here's an example of reading a batch of records and printing out
|
|
@@ -110,7 +97,7 @@ MARC](http://www.loc.gov/marc/umb/) is a pretty good primer, and the [MARC 21
|
|
|
110
97
|
Formats](http://www.loc.gov/marc/marcdocz.html) page at the Library of Congress
|
|
111
98
|
is a good reference once you understand the basics.
|
|
112
99
|
|
|
113
|
-
|
|
100
|
+
## Writing
|
|
114
101
|
|
|
115
102
|
*Note: As of v5.0.0 `Subfield` is used to create subfields. Prior to v5,
|
|
116
103
|
subfields were constructed and accessed as a list of strings, e.g., `[code,
|
|
@@ -155,7 +142,7 @@ legacy_fields: list[str] = ['a', 'The pragmatic programmer : ',
|
|
|
155
142
|
coded_fields: list[Subfield] = Field.convert_legacy_subfields(legacy_fields)
|
|
156
143
|
```
|
|
157
144
|
|
|
158
|
-
|
|
145
|
+
## Updating
|
|
159
146
|
|
|
160
147
|
Updating works the same way, you read it in, modify it, and then write it out
|
|
161
148
|
again:
|
|
@@ -171,7 +158,7 @@ with open('file.dat', 'wb') as out:
|
|
|
171
158
|
```
|
|
172
159
|
|
|
173
160
|
|
|
174
|
-
|
|
161
|
+
## JSON and XML
|
|
175
162
|
|
|
176
163
|
If you find yourself using MARC data a fair bit, and distributing it, you may
|
|
177
164
|
make other developers a bit happier by using the JSON or XML serializations. The
|
|
@@ -379,8 +366,38 @@ print(records[0])
|
|
|
379
366
|
=700 1\$aCharles, Ray,$d1930-$4prf
|
|
380
367
|
```
|
|
381
368
|
|
|
382
|
-
|
|
383
|
-
|
|
369
|
+
## Developing
|
|
370
|
+
|
|
371
|
+
If you'd like to further develop pymarc you'll want to get the latest code:
|
|
372
|
+
|
|
373
|
+
git clone git://gitlab.com/pymarc/pymarc.git
|
|
374
|
+
cd pymarc
|
|
375
|
+
|
|
376
|
+
Create a virtual environment with [uv](https://docs.astral.sh/uv/) and activate it:
|
|
377
|
+
|
|
378
|
+
pip install uv
|
|
379
|
+
uv venv
|
|
380
|
+
uv sync
|
|
381
|
+
source .venv/bin/activate
|
|
382
|
+
|
|
383
|
+
Run the tests:
|
|
384
|
+
|
|
385
|
+
pytest
|
|
386
|
+
|
|
387
|
+
Run the lint tests:
|
|
388
|
+
|
|
389
|
+
flake8 .
|
|
390
|
+
|
|
391
|
+
And run type checking:
|
|
392
|
+
|
|
393
|
+
mypy --ignore-missing-imports .
|
|
394
|
+
|
|
395
|
+
If you want to build and publish a new version of pymarc on PyPI you can:
|
|
396
|
+
|
|
397
|
+
hatch build
|
|
398
|
+
hatch release
|
|
399
|
+
|
|
400
|
+
## Support
|
|
384
401
|
|
|
385
402
|
The pymarc developers encourage you to join the [pymarc Google
|
|
386
403
|
Group](http://groups.google.com/group/pymarc) if you need help. Also, please
|
|
@@ -389,6 +406,6 @@ GitLab to submit feature requests or bug reports. If you've got an itch to
|
|
|
389
406
|
scratch, please scratch it, and send merge requests on
|
|
390
407
|
[GitLab](http://gitlab.com/pymarc/pymarc).
|
|
391
408
|
|
|
392
|
-
If you start working with MARC you may feel like you need moral support
|
|
393
|
-
|
|
394
|
-
|
|
409
|
+
If you start working with MARC you may feel like you need moral support in
|
|
410
|
+
addition to technical support. The #python channel on [code4lib Slack]https://code4lib.org/slack/)
|
|
411
|
+
is a good place to start.
|
|
@@ -33,11 +33,7 @@ Se você quiser baixar e instalar a versão mais recente, precisará do git:
|
|
|
33
33
|
|
|
34
34
|
Você também vai precisar do [setuptools](https://pypi.python.org/pypi/setuptools#installation-instructions). Após ter a fonte e o setuptools, execute o pymarc test suite para garantirque as tudo está em ordem com a distribuição:
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
E então instale:
|
|
39
|
-
|
|
40
|
-
python setup.py install
|
|
36
|
+
pytest
|
|
41
37
|
|
|
42
38
|
### Leitura
|
|
43
39
|
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Apply standard license headers and generate contributor list.
|
|
4
|
+
|
|
5
|
+
Rather than trying to maintain file-level lists of contributors and copyright
|
|
6
|
+
dates, apply a standard license header that points to the LICENSE file for the
|
|
7
|
+
licensing details. And then generate the LICENSE file with a complete list of
|
|
8
|
+
contributors based on the git commit history.
|
|
9
|
+
|
|
10
|
+
To adjust contributor names or combine email addresses, see .mailmap.
|
|
11
|
+
|
|
12
|
+
See https://github.com/edsu/pymarc/issues/147 for context.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
# This file is part of pymarc. It is subject to the license terms in the
|
|
16
|
+
# LICENSE file found in the top-level directory of this distribution and at
|
|
17
|
+
# https://opensource.org/licenses/BSD-2-Clause. pymarc may be copied, modified,
|
|
18
|
+
# propagated, or distributed according to the terms contained in the LICENSE
|
|
19
|
+
# file.
|
|
20
|
+
|
|
21
|
+
import pathlib
|
|
22
|
+
import shlex
|
|
23
|
+
import subprocess
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_contributors():
|
|
27
|
+
"""Get a complete list of contributors from `git log`."""
|
|
28
|
+
# dictionary = add each name only once
|
|
29
|
+
contribs = {}
|
|
30
|
+
|
|
31
|
+
gitargs = shlex.split("git log --use-mailmap --format=short")
|
|
32
|
+
log = subprocess.run(gitargs, capture_output=True, encoding="utf-8")
|
|
33
|
+
for line in log.stdout.split("\n"):
|
|
34
|
+
if line[0 : len("Author: ")] == "Author: ":
|
|
35
|
+
contribs[line[len("Author: ") :]] = 1
|
|
36
|
+
|
|
37
|
+
# Return a list of the contributors
|
|
38
|
+
return sorted(contribs)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def generate_license(contribs):
|
|
42
|
+
"""Generate a BSD-2 license file that lists contributors."""
|
|
43
|
+
bsd2 = """Redistribution and use in source and binary forms, with or without
|
|
44
|
+
modification, are permitted provided that the following conditions are met:
|
|
45
|
+
|
|
46
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
47
|
+
list of conditions and the following disclaimer.
|
|
48
|
+
|
|
49
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
50
|
+
this list of conditions and the following disclaimer in the documentation
|
|
51
|
+
and/or other materials provided with the distribution.
|
|
52
|
+
|
|
53
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
54
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
56
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
57
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
58
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
59
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
60
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
61
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
62
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
with open("LICENSE", "w") as licensef:
|
|
67
|
+
licensef.write(bsd2)
|
|
68
|
+
licensef.write(
|
|
69
|
+
"Copyright for this project is held by its many contributors, including:\n\n"
|
|
70
|
+
)
|
|
71
|
+
for contrib in contribs:
|
|
72
|
+
licensef.write("{}\n".format(contrib))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def apply_headers():
|
|
76
|
+
"""Ensure standard license header is in each Python file."""
|
|
77
|
+
header = """# This file is part of pymarc. It is subject to the license terms in the
|
|
78
|
+
# LICENSE file found in the top-level directory of this distribution and at
|
|
79
|
+
# https://opensource.org/licenses/BSD-2-Clause. pymarc may be copied, modified,
|
|
80
|
+
# propagated, or distributed according to the terms contained in the LICENSE
|
|
81
|
+
# file.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
path = pathlib.Path(".")
|
|
85
|
+
for pyfile in list(path.glob("**/*.py")):
|
|
86
|
+
if str(pyfile) == "docs/source/conf.py" or str(pyfile) == "test/__init__.py":
|
|
87
|
+
continue
|
|
88
|
+
with open(pyfile, "r") as reader:
|
|
89
|
+
contents = reader.read()
|
|
90
|
+
if contents.find(header) == -1:
|
|
91
|
+
if str(pyfile) == "test/__init__.py":
|
|
92
|
+
# Avoid angering black with a blank line at the end
|
|
93
|
+
write_header(pyfile, reader, contents, header)
|
|
94
|
+
else:
|
|
95
|
+
write_header(pyfile, reader, contents, header + "\n")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def write_header(pyfile, reader, contents, header):
|
|
99
|
+
"""Rewrite Python source file with the license header."""
|
|
100
|
+
reader.close()
|
|
101
|
+
utf8_decl = "# -*- coding: utf-8 -*-\n"
|
|
102
|
+
with open(pyfile, "w") as writer:
|
|
103
|
+
if contents.startswith("# __init__.py"):
|
|
104
|
+
sections = contents.split("\n\n", 1)
|
|
105
|
+
writer.write(sections[0])
|
|
106
|
+
writer.write("\n\n")
|
|
107
|
+
writer.write(header)
|
|
108
|
+
writer.write(sections[1])
|
|
109
|
+
elif contents.startswith(utf8_decl):
|
|
110
|
+
sections = contents.split(utf8_decl, 1)
|
|
111
|
+
writer.write(utf8_decl)
|
|
112
|
+
writer.write("\n")
|
|
113
|
+
writer.write(header)
|
|
114
|
+
writer.write(sections[1])
|
|
115
|
+
else:
|
|
116
|
+
writer.write(header)
|
|
117
|
+
writer.write(contents)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if __name__ == "__main__":
|
|
121
|
+
generate_license(get_contributors())
|
|
122
|
+
apply_headers()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sphinx-rtd-theme
|
|
@@ -65,20 +65,6 @@ project = "pymarc"
|
|
|
65
65
|
copyright = "Contributors listed in the accompanying LICENSE file"
|
|
66
66
|
author = "Ed Summers"
|
|
67
67
|
|
|
68
|
-
# The version info for the project you're documenting, acts as replacement for
|
|
69
|
-
# |version| and |release|, also used in various other places throughout the
|
|
70
|
-
# built documents.
|
|
71
|
-
#
|
|
72
|
-
# The short X.Y version.
|
|
73
|
-
version = "4.0.0"
|
|
74
|
-
with open(os.path.join(os.path.dirname(__file__), "../../setup.py")) as setup_file:
|
|
75
|
-
for line in setup_file:
|
|
76
|
-
if line.startswith("version"):
|
|
77
|
-
__, version = line.split(" = ")
|
|
78
|
-
version = version.replace('"', "")
|
|
79
|
-
break
|
|
80
|
-
release = version
|
|
81
|
-
|
|
82
68
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
83
69
|
# for a list of supported languages.
|
|
84
70
|
#
|
|
@@ -12,6 +12,8 @@ from typing import List, Optional, DefaultDict, NamedTuple, Iterator, Dict, Sequ
|
|
|
12
12
|
from pymarc.constants import SUBFIELD_INDICATOR, END_OF_FIELD
|
|
13
13
|
from pymarc.marc8 import marc8_to_unicode
|
|
14
14
|
|
|
15
|
+
logger = logging.getLogger("pymarc")
|
|
16
|
+
|
|
15
17
|
Subfield = NamedTuple("Subfield", [("code", str), ("value", str)])
|
|
16
18
|
|
|
17
19
|
|
|
@@ -467,7 +469,7 @@ class RawField(Field):
|
|
|
467
469
|
def as_marc(self, encoding: Optional[str] = None):
|
|
468
470
|
"""Used during conversion of a field to raw MARC."""
|
|
469
471
|
if encoding is not None:
|
|
470
|
-
|
|
472
|
+
logger.warning("Attempt to force a RawField into encoding %s", encoding)
|
|
471
473
|
if self.control_field:
|
|
472
474
|
return self.data + END_OF_FIELD.encode("ascii") # type: ignore
|
|
473
475
|
marc: bytes = self.indicator1.encode("ascii") + self.indicator2.encode("ascii")
|
|
@@ -37,6 +37,7 @@ from pymarc.leader import Leader
|
|
|
37
37
|
from pymarc.marc8 import marc8_to_unicode
|
|
38
38
|
|
|
39
39
|
isbn_regex: Pattern = re.compile(r"([0-9\-xX]+)")
|
|
40
|
+
logger = logging.getLogger("pymarc")
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
class Record:
|
|
@@ -367,14 +368,14 @@ class Record:
|
|
|
367
368
|
first_indicator = second_indicator = " "
|
|
368
369
|
subs[0] = subs[0].decode("ascii")
|
|
369
370
|
if len(subs[0]) == 0:
|
|
370
|
-
|
|
371
|
+
logger.warning("missing indicators: %s", entry_data)
|
|
371
372
|
first_indicator = second_indicator = " "
|
|
372
373
|
elif len(subs[0]) == 1:
|
|
373
|
-
|
|
374
|
+
logger.warning("only 1 indicator found: %s", entry_data)
|
|
374
375
|
first_indicator = subs[0][0]
|
|
375
376
|
second_indicator = " "
|
|
376
377
|
elif len(subs[0]) > 2:
|
|
377
|
-
|
|
378
|
+
logger.warning("more than 2 indicators found: %s", entry_data)
|
|
378
379
|
first_indicator = subs[0][0]
|
|
379
380
|
second_indicator = subs[0][1]
|
|
380
381
|
else:
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pymarc"
|
|
3
|
+
version = "5.2.3"
|
|
4
|
+
description = "Read, write and modify MARC bibliographic data"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.8"
|
|
7
|
+
license = {file = "LICENSE"}
|
|
8
|
+
dependencies = []
|
|
9
|
+
packages = ["pymarc"]
|
|
10
|
+
|
|
11
|
+
[build-system]
|
|
12
|
+
requires = ["hatchling"]
|
|
13
|
+
build-backend = "hatchling.build"
|
|
14
|
+
|
|
15
|
+
[tool.uv]
|
|
16
|
+
dev-dependencies = [
|
|
17
|
+
"black>=23.3.0",
|
|
18
|
+
"flake8>=5.0.4",
|
|
19
|
+
"flake8-docstrings>=1.7.0",
|
|
20
|
+
"mypy>=1.4.1",
|
|
21
|
+
"wheel>=0.42.0",
|
|
22
|
+
"pytest>=7.4.4",
|
|
23
|
+
"hatch>=0.23.1",
|
|
24
|
+
"coverage>=7.2.7",
|
|
25
|
+
]
|