folio-migration-tools 1.10.0b3__py3-none-any.whl → 1.10.0b6__py3-none-any.whl
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.
- folio_migration_tools/__main__.py +9 -0
- folio_migration_tools/folder_structure.py +0 -3
- folio_migration_tools/mapping_file_transformation/user_mapper.py +4 -0
- folio_migration_tools/marc_rules_transformation/conditions.py +0 -29
- folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +0 -6
- folio_migration_tools/migration_tasks/batch_poster.py +216 -295
- folio_migration_tools/migration_tasks/migration_task_base.py +13 -5
- folio_migration_tools/migration_tasks/user_transformer.py +10 -0
- folio_migration_tools/translations/en.json +0 -7
- {folio_migration_tools-1.10.0b3.dist-info → folio_migration_tools-1.10.0b6.dist-info}/METADATA +2 -2
- {folio_migration_tools-1.10.0b3.dist-info → folio_migration_tools-1.10.0b6.dist-info}/RECORD +13 -15
- folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +0 -242
- folio_migration_tools/migration_tasks/authority_transformer.py +0 -118
- {folio_migration_tools-1.10.0b3.dist-info → folio_migration_tools-1.10.0b6.dist-info}/WHEEL +0 -0
- {folio_migration_tools-1.10.0b3.dist-info → folio_migration_tools-1.10.0b6.dist-info}/entry_points.txt +0 -0
|
@@ -99,6 +99,7 @@ class MigrationTaskBase:
|
|
|
99
99
|
raise NotImplementedError()
|
|
100
100
|
|
|
101
101
|
def clean_out_empty_logs(self):
|
|
102
|
+
_close_handler(self.data_issue_file_handler)
|
|
102
103
|
if (
|
|
103
104
|
self.folder_structure.data_issue_file_path.is_file()
|
|
104
105
|
and os.stat(self.folder_structure.data_issue_file_path).st_size == 0
|
|
@@ -260,13 +261,13 @@ class MigrationTaskBase:
|
|
|
260
261
|
|
|
261
262
|
# Data issue file formatter
|
|
262
263
|
data_issue_file_formatter = logging.Formatter("%(message)s")
|
|
263
|
-
data_issue_file_handler = logging.FileHandler(
|
|
264
|
+
self.data_issue_file_handler = logging.FileHandler(
|
|
264
265
|
filename=str(self.folder_structure.data_issue_file_path), mode="w"
|
|
265
266
|
)
|
|
266
|
-
data_issue_file_handler.addFilter(LevelFilter(26))
|
|
267
|
-
data_issue_file_handler.setFormatter(data_issue_file_formatter)
|
|
268
|
-
data_issue_file_handler.setLevel(26)
|
|
269
|
-
logging.getLogger().addHandler(data_issue_file_handler)
|
|
267
|
+
self.data_issue_file_handler.addFilter(LevelFilter(26))
|
|
268
|
+
self.data_issue_file_handler.setFormatter(data_issue_file_formatter)
|
|
269
|
+
self.data_issue_file_handler.setLevel(26)
|
|
270
|
+
logging.getLogger().addHandler(self.data_issue_file_handler)
|
|
270
271
|
logger.info("Logging set up")
|
|
271
272
|
|
|
272
273
|
def setup_records_map(self, mapping_file_path):
|
|
@@ -553,3 +554,10 @@ class LevelFilter(logging.Filter):
|
|
|
553
554
|
|
|
554
555
|
def filter(self, record):
|
|
555
556
|
return record.levelno == self.level
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
def _close_handler(handler: logging.Handler | None):
|
|
560
|
+
if handler is None:
|
|
561
|
+
return
|
|
562
|
+
handler.flush()
|
|
563
|
+
handler.close()
|
|
@@ -101,6 +101,16 @@ class UserTransformer(MigrationTaskBase):
|
|
|
101
101
|
),
|
|
102
102
|
),
|
|
103
103
|
] = False
|
|
104
|
+
remove_username: Annotated[
|
|
105
|
+
Optional[bool],
|
|
106
|
+
Field(
|
|
107
|
+
title="Remove username",
|
|
108
|
+
description=(
|
|
109
|
+
"Specify whether to remove username. Resulting objects are not compatible with"
|
|
110
|
+
" the mod-user-import. Optional, by default is False"
|
|
111
|
+
),
|
|
112
|
+
),
|
|
113
|
+
] = False
|
|
104
114
|
|
|
105
115
|
@staticmethod
|
|
106
116
|
def get_object_type() -> FOLIONamespaces:
|
|
@@ -24,7 +24,6 @@
|
|
|
24
24
|
"Aged to lost and checked out": "Aged to lost and checked out",
|
|
25
25
|
"Already set to %{value}. %{leader_key} was %{leader}": "Already set to %{value}. %{leader_key} was %{leader}",
|
|
26
26
|
"An Unmapped": "An Unmapped",
|
|
27
|
-
"Authority records transformation report": "Authority records transformation report",
|
|
28
27
|
"BW Items found tied to previously created BW Holdings": "BW Items found tied to previously created BW Holdings",
|
|
29
28
|
"Bib identifier not in instances_id_map, no instance linked": "Bib identifier not in instances_id_map, no instance linked",
|
|
30
29
|
"Bib ids referenced in bound-with items": "Bib ids referenced in bound-with items",
|
|
@@ -264,12 +263,6 @@
|
|
|
264
263
|
"blurbs.AcquisitionMethodMapping.title": "POL Acquisition Method Mapping",
|
|
265
264
|
"blurbs.AddedValueFromParameter.description": "",
|
|
266
265
|
"blurbs.AddedValueFromParameter.title": "Added value from parameter since value is empty",
|
|
267
|
-
"blurbs.AuthorityEncodingLevel.description": "Library action: **All values that are not n or o will be set to n. If this is not what you want, you need to correct these values in your system. **<br/>An overview of the Encoding levels (Leader position 17) present in your source data. Allowed values according to the MARC standard are n or o",
|
|
268
|
-
"blurbs.AuthorityEncodingLevel.title": "Encoding level (leader pos 17)",
|
|
269
|
-
"blurbs.AuthoritySourceFileMapping.description": "Mappings based on FOLIO authority `naturalId` alpha prefix",
|
|
270
|
-
"blurbs.AuthoritySourceFileMapping.title": "Authority Source File Mapping Results",
|
|
271
|
-
"blurbs.AuthoritySources.description": "",
|
|
272
|
-
"blurbs.AuthoritySources.title": "Authorization sources and related information",
|
|
273
266
|
"blurbs.BoundWithMappings.description": "",
|
|
274
267
|
"blurbs.BoundWithMappings.title": "Bound-with mapping",
|
|
275
268
|
"blurbs.CallNumberTypeMapping.description": "Call number types in MFHDs are mapped from 852, Indicator 1 according to a certain scheme. (LOC documentation)[https://www.loc.gov/marc/holdings/hd852.html]",
|
{folio_migration_tools-1.10.0b3.dist-info → folio_migration_tools-1.10.0b6.dist-info}/METADATA
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: folio-migration-tools
|
|
3
|
-
Version: 1.10.
|
|
3
|
+
Version: 1.10.0b6
|
|
4
4
|
Summary: A tool allowing you to migrate data from legacy ILS:s (Library systems) into FOLIO LSP
|
|
5
5
|
Keywords: FOLIO,ILS,LSP,Library Systems,MARC21,Library data
|
|
6
6
|
Author: Theodor Tolstoy, Lisa Sjögren, Brooks Travis, Jeremy Nelson, Clinton Bradford
|
|
7
7
|
Author-email: Theodor Tolstoy <github.teddes@tolstoy.se>, Brooks Travis <brooks.travis@gmail.com>
|
|
8
8
|
License-Expression: MIT
|
|
9
|
-
Requires-Dist: folioclient>=1.0.
|
|
9
|
+
Requires-Dist: folioclient>=1.0.4
|
|
10
10
|
Requires-Dist: pyhumps>=3.7.3,<4.0.0
|
|
11
11
|
Requires-Dist: defusedxml>=0.7.1,<1.0.0
|
|
12
12
|
Requires-Dist: python-dateutil>=2.8.2,<3.0.0
|
{folio_migration_tools-1.10.0b3.dist-info → folio_migration_tools-1.10.0b6.dist-info}/RECORD
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
folio_migration_tools/__init__.py,sha256=lnYgqA47l0iA-iORkVH3dgevk7gyGxVwg3MnLltA-U8,223
|
|
2
|
-
folio_migration_tools/__main__.py,sha256=
|
|
2
|
+
folio_migration_tools/__main__.py,sha256=KJdmLkKwAygTKuIKfvDL3M0JdVgsCbf2_LTL1FP6GxU,9233
|
|
3
3
|
folio_migration_tools/circulation_helper.py,sha256=r1zpOKy47VFRHyXHvwUEjPfQ4jyJpjMAYc1IktJ94WU,14661
|
|
4
4
|
folio_migration_tools/colors.py,sha256=GP0wdI_GZ2WD5SjrbPN-S3u8vvN_u6rGQIBBcWv_0ZM,227
|
|
5
5
|
folio_migration_tools/config_file_load.py,sha256=zHHa6NDkN6EJiQE4DgjrFQPVKsd70POsfbGkB8308jg,2822
|
|
6
6
|
folio_migration_tools/custom_dict.py,sha256=rRd9_RQqI85171p7wTfpMM0Mladh-LChbgMSmLvN7N0,680
|
|
7
7
|
folio_migration_tools/custom_exceptions.py,sha256=BLP1gMPbTHSN-rqxzTawT4sRLiyAU3blBdkUBwiiPRk,2642
|
|
8
8
|
folio_migration_tools/extradata_writer.py,sha256=fuchNcMc6BYb9IyfAcvXg7X4J2TfX6YiROfT2hr0JMw,1678
|
|
9
|
-
folio_migration_tools/folder_structure.py,sha256=
|
|
9
|
+
folio_migration_tools/folder_structure.py,sha256=ExrXNEWvCB5QMH17kQSyTDQ04thq--t8_p3F_iuyf0k,6776
|
|
10
10
|
folio_migration_tools/helper.py,sha256=Jb-9PrMkgOUGYScRf8jMmGGTcPIohm3eFHenGSi3cUA,2979
|
|
11
11
|
folio_migration_tools/holdings_helper.py,sha256=yJpz6aJrKRBiJ1MtT5bs2vXAc88uJuGh2_KDuCySOKc,7559
|
|
12
12
|
folio_migration_tools/i18n_config.py,sha256=3AH_2b9zTsxE4XTe4isM_zYtPJSlK0ix6eBmV7kAYUM,228
|
|
@@ -22,22 +22,20 @@ folio_migration_tools/mapping_file_transformation/notes_mapper.py,sha256=vCmZmjr
|
|
|
22
22
|
folio_migration_tools/mapping_file_transformation/order_mapper.py,sha256=VUcbeBGlQ7KsDPgJlaOOe8bO0y5IRLTCBH_IQKcaqiA,18267
|
|
23
23
|
folio_migration_tools/mapping_file_transformation/organization_mapper.py,sha256=MKlN3doQ_R-Y3klkbCFL4qHUfhMATBsIhvq1jpmajqQ,14641
|
|
24
24
|
folio_migration_tools/mapping_file_transformation/ref_data_mapping.py,sha256=rROcBiL5TE7bWsJ95A6shurPZ1e4In6PTwR5BN9amzU,8991
|
|
25
|
-
folio_migration_tools/mapping_file_transformation/user_mapper.py,sha256=
|
|
25
|
+
folio_migration_tools/mapping_file_transformation/user_mapper.py,sha256=nqyoSQAo3IGAAzXVRM-R0M5Q83zS3uU6jvKx4_c1mt8,8940
|
|
26
26
|
folio_migration_tools/marc_rules_transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
|
-
folio_migration_tools/marc_rules_transformation/conditions.py,sha256
|
|
27
|
+
folio_migration_tools/marc_rules_transformation/conditions.py,sha256=-5U6nBGcBO49C9MMyxOL2wMhHGxUawkIM9e-MwNaM_4,46938
|
|
28
28
|
folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py,sha256=-mOGtoPa3qmEqGWtyBTN-fQ743ZmT8caDLc9ES9J74Y,13667
|
|
29
29
|
folio_migration_tools/marc_rules_transformation/hrid_handler.py,sha256=WudBOzCwcJAuhEm4urLhAk5OQWGfbKz9_4Ou8fmjm1E,10022
|
|
30
30
|
folio_migration_tools/marc_rules_transformation/loc_language_codes.xml,sha256=ztn2_yKws6qySL4oSsZh7sOjxq5bCC1PhAnXJdtgmJ0,382912
|
|
31
31
|
folio_migration_tools/marc_rules_transformation/marc_file_processor.py,sha256=o03d_G-4MR4e5VPfu7ljxAVDl79o2ONpQIqQ-V2RCdA,12523
|
|
32
32
|
folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py,sha256=9ATjYMRAjy0QcXtmNZaHVhHLJ5hE1WUgOcF6KMJjbgo,5309
|
|
33
|
-
folio_migration_tools/marc_rules_transformation/
|
|
34
|
-
folio_migration_tools/marc_rules_transformation/rules_mapper_base.py,sha256=ijOs9r0Mcx0XyNhDAq7fw1aFJ-JnAEhHx98-t262uRo,46158
|
|
33
|
+
folio_migration_tools/marc_rules_transformation/rules_mapper_base.py,sha256=KxyZjizbLwwAY2PfMSyh6u_mVTpfhyvdaii_PlpLscw,45857
|
|
35
34
|
folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py,sha256=F8tKn59zHUV3Gqa9NY-JvTbWgfDjNTcPvQONk8gzwGs,30428
|
|
36
35
|
folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=YILyEfO-LkQPk-4OjiuY68X5xDA0LlI7UUp7_mvzLUE,29184
|
|
37
36
|
folio_migration_tools/migration_report.py,sha256=B8e4tMfT0xCJ3BxkSg7ZZJYmg0VLQVXmmVnWwmojZD4,4260
|
|
38
37
|
folio_migration_tools/migration_tasks/__init__.py,sha256=ZkbY_yGyB84Ke8OMlYUzyyBj4cxxNrhMTwQlu_GbdDs,211
|
|
39
|
-
folio_migration_tools/migration_tasks/
|
|
40
|
-
folio_migration_tools/migration_tasks/batch_poster.py,sha256=x3DQPrI1QnRtg9Bdf-e3ztv4llWPt5JpeCIyE7mMNWU,50634
|
|
38
|
+
folio_migration_tools/migration_tasks/batch_poster.py,sha256=rbSx3dyF4UbNdFiAhBRDpBTvAwQI3BR4s4_sIBsM-70,46214
|
|
41
39
|
folio_migration_tools/migration_tasks/bibs_transformer.py,sha256=zPxh2tjyqx88fuH1FuKLwhT6lhZ5fVTQAqE08IggYgM,6351
|
|
42
40
|
folio_migration_tools/migration_tasks/courses_migrator.py,sha256=sKIeyUlc7o189lw88XbGILVkwnR9krqO0PgS-vLCCm8,7039
|
|
43
41
|
folio_migration_tools/migration_tasks/holdings_csv_transformer.py,sha256=JzOufqjSR2V-gUvOq0pdQFsXjpxk1ldGJBQWIWGfCps,21915
|
|
@@ -45,20 +43,20 @@ folio_migration_tools/migration_tasks/holdings_marc_transformer.py,sha256=b1lWbY
|
|
|
45
43
|
folio_migration_tools/migration_tasks/items_transformer.py,sha256=gIJ9SKUENE3OaEouGAFTsGjciN_YxwRoUAAEKJlfG-E,19498
|
|
46
44
|
folio_migration_tools/migration_tasks/loans_migrator.py,sha256=6mwtA9-6B_pU1GKS9VD7Wu5stZ8YLlyeliFJhyPuho0,38785
|
|
47
45
|
folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py,sha256=CnmlTge7nChUJ10EiUkriQtJlVxWqglgfhjgneh2_yM,7247
|
|
48
|
-
folio_migration_tools/migration_tasks/migration_task_base.py,sha256=
|
|
46
|
+
folio_migration_tools/migration_tasks/migration_task_base.py,sha256=rhIYFZ_dYWEyopkR2shht5ybKk4JQzxctSlBizml50g,22551
|
|
49
47
|
folio_migration_tools/migration_tasks/orders_transformer.py,sha256=h8EyRbvbtwDZJq1y73J7oZFRdI1U4vq1Vrlay4GLf4M,13885
|
|
50
48
|
folio_migration_tools/migration_tasks/organization_transformer.py,sha256=5s-ACb9-R8JLlPnROOq1ZnDIRCLQeWaxORDn0SrhQqs,16747
|
|
51
49
|
folio_migration_tools/migration_tasks/requests_migrator.py,sha256=Q7sWOxqq73Fdg3Q1tmpvRxU9qhhG1BV3AGMoCMwh2cE,14768
|
|
52
50
|
folio_migration_tools/migration_tasks/reserves_migrator.py,sha256=jdiwWAlMydXE2vlv0lgHRUljarslveyVOu-TCnymAEs,9953
|
|
53
|
-
folio_migration_tools/migration_tasks/user_transformer.py,sha256=
|
|
51
|
+
folio_migration_tools/migration_tasks/user_transformer.py,sha256=apgVCoJQ4sB5aFp7p8FdSQrDfXSIzgEbEQ3C-6dG568,12621
|
|
54
52
|
folio_migration_tools/task_configuration.py,sha256=6eqbjjSWfi-qgp0bhCsuBVE3gTK4HaXzXsAo68JPGc0,1146
|
|
55
53
|
folio_migration_tools/transaction_migration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
56
54
|
folio_migration_tools/transaction_migration/legacy_loan.py,sha256=A5qvThfP3g62YnykLyti_tqTY7dq1SbLi3WZz7QXk6s,7399
|
|
57
55
|
folio_migration_tools/transaction_migration/legacy_request.py,sha256=Kv7jpBIuZ_qyay8BdaeCPJID67l43Cl6x-ws9Lt49NI,6121
|
|
58
56
|
folio_migration_tools/transaction_migration/legacy_reserve.py,sha256=qzw0okg4axAE_ezXopP9gFsQ_e60o0zh7zqRzFBSWHY,1806
|
|
59
57
|
folio_migration_tools/transaction_migration/transaction_result.py,sha256=cTdCN0BnlI9_ZJB2Z3Fdkl9gpymIi-9mGZsRFlQcmDk,656
|
|
60
|
-
folio_migration_tools/translations/en.json,sha256=
|
|
61
|
-
folio_migration_tools-1.10.
|
|
62
|
-
folio_migration_tools-1.10.
|
|
63
|
-
folio_migration_tools-1.10.
|
|
64
|
-
folio_migration_tools-1.10.
|
|
58
|
+
folio_migration_tools/translations/en.json,sha256=pS7dhHmj4XBqTcFNIcqFgRMY557fQan1RomdNg6PtdA,40941
|
|
59
|
+
folio_migration_tools-1.10.0b6.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
60
|
+
folio_migration_tools-1.10.0b6.dist-info/entry_points.txt,sha256=mJRRiCNP9j7_NpVXamHEiW8pDEjWQs1vEqD89G354cM,79
|
|
61
|
+
folio_migration_tools-1.10.0b6.dist-info/METADATA,sha256=EcDMNh4diSH6vDbrIQWdk-kcTdM2W2Agw3X4lo22h2Y,7162
|
|
62
|
+
folio_migration_tools-1.10.0b6.dist-info/RECORD,,
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
"""The default mapper, responsible for parsing MARC21 records acording to the
|
|
2
|
-
FOLIO community specifications"""
|
|
3
|
-
|
|
4
|
-
import logging
|
|
5
|
-
import re
|
|
6
|
-
import time
|
|
7
|
-
import uuid
|
|
8
|
-
from typing import List
|
|
9
|
-
|
|
10
|
-
import i18n
|
|
11
|
-
import pymarc
|
|
12
|
-
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
13
|
-
from folio_uuid.folio_uuid import FolioUUID
|
|
14
|
-
from folioclient import FolioClient
|
|
15
|
-
from pymarc import Leader, Record
|
|
16
|
-
|
|
17
|
-
from folio_migration_tools.custom_exceptions import TransformationProcessError
|
|
18
|
-
from folio_migration_tools.helper import Helper
|
|
19
|
-
from folio_migration_tools.library_configuration import (
|
|
20
|
-
FileDefinition,
|
|
21
|
-
IlsFlavour,
|
|
22
|
-
LibraryConfiguration,
|
|
23
|
-
)
|
|
24
|
-
from folio_migration_tools.marc_rules_transformation.conditions import Conditions
|
|
25
|
-
from folio_migration_tools.marc_rules_transformation.hrid_handler import HRIDHandler
|
|
26
|
-
from folio_migration_tools.marc_rules_transformation.rules_mapper_base import (
|
|
27
|
-
RulesMapperBase,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class AuthorityMapper(RulesMapperBase):
|
|
32
|
-
non_repatable_fields = [
|
|
33
|
-
"100",
|
|
34
|
-
"110",
|
|
35
|
-
"111",
|
|
36
|
-
"130",
|
|
37
|
-
"147",
|
|
38
|
-
"148",
|
|
39
|
-
"150",
|
|
40
|
-
"151",
|
|
41
|
-
"155",
|
|
42
|
-
"162",
|
|
43
|
-
"180",
|
|
44
|
-
"181",
|
|
45
|
-
"182",
|
|
46
|
-
"185",
|
|
47
|
-
"378",
|
|
48
|
-
"384",
|
|
49
|
-
]
|
|
50
|
-
"""_summary_
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
RulesMapperBase (_type_): _description_
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
def __init__(
|
|
57
|
-
self,
|
|
58
|
-
folio_client,
|
|
59
|
-
library_configuration: LibraryConfiguration,
|
|
60
|
-
task_configuration,
|
|
61
|
-
):
|
|
62
|
-
super().__init__(
|
|
63
|
-
folio_client,
|
|
64
|
-
library_configuration,
|
|
65
|
-
task_configuration,
|
|
66
|
-
None,
|
|
67
|
-
self.get_authority_json_schema(folio_client, library_configuration),
|
|
68
|
-
Conditions(folio_client, self, "auth", library_configuration.folio_release),
|
|
69
|
-
)
|
|
70
|
-
self.srs_recs: list = []
|
|
71
|
-
logging.info("Fetching mapping rules from the tenant")
|
|
72
|
-
rules_endpoint = "/mapping-rules/marc-authority"
|
|
73
|
-
self.mappings = self.folio_client.folio_get_single_object(rules_endpoint)
|
|
74
|
-
self.source_file_mapping: dict = {}
|
|
75
|
-
self.setup_source_file_mapping()
|
|
76
|
-
self.start = time.time()
|
|
77
|
-
|
|
78
|
-
def get_legacy_ids(self, marc_record: Record, idx: int) -> List[str]:
|
|
79
|
-
ils_flavour: IlsFlavour = self.task_configuration.ils_flavour
|
|
80
|
-
if ils_flavour in {IlsFlavour.sierra, IlsFlavour.millennium}:
|
|
81
|
-
raise TransformationProcessError("", f"ILS {ils_flavour} not configured")
|
|
82
|
-
elif ils_flavour == IlsFlavour.tag907y:
|
|
83
|
-
return RulesMapperBase.get_bib_id_from_907y(marc_record, idx)
|
|
84
|
-
elif ils_flavour == IlsFlavour.tagf990a:
|
|
85
|
-
return RulesMapperBase.get_bib_id_from_990a(marc_record, idx)
|
|
86
|
-
elif ils_flavour == IlsFlavour.aleph:
|
|
87
|
-
raise TransformationProcessError("", f"ILS {ils_flavour} not configured")
|
|
88
|
-
elif ils_flavour in {IlsFlavour.voyager, "voyager", IlsFlavour.tag001}:
|
|
89
|
-
return RulesMapperBase.get_bib_id_from_001(marc_record, idx)
|
|
90
|
-
elif ils_flavour == IlsFlavour.koha:
|
|
91
|
-
raise TransformationProcessError("", f"ILS {ils_flavour} not configured")
|
|
92
|
-
elif ils_flavour == IlsFlavour.none:
|
|
93
|
-
return [str(uuid.uuid4())]
|
|
94
|
-
else:
|
|
95
|
-
raise TransformationProcessError("", f"ILS {ils_flavour} not configured")
|
|
96
|
-
|
|
97
|
-
def parse_record(
|
|
98
|
-
self, marc_record: pymarc.Record, file_def: FileDefinition, legacy_ids: List[str]
|
|
99
|
-
) -> list[dict]:
|
|
100
|
-
"""Parses an auth recod into a FOLIO Authority object
|
|
101
|
-
This is the main function
|
|
102
|
-
|
|
103
|
-
Args:
|
|
104
|
-
legacy_ids (_type_): _description_
|
|
105
|
-
marc_record (Record): _description_
|
|
106
|
-
file_def (FileDefinition): _description_
|
|
107
|
-
|
|
108
|
-
Returns:
|
|
109
|
-
dict: _description_
|
|
110
|
-
"""
|
|
111
|
-
self.print_progress()
|
|
112
|
-
ignored_subsequent_fields: set = set()
|
|
113
|
-
bad_tags = set(self.task_configuration.tags_to_delete) # "907"
|
|
114
|
-
folio_authority = self.perform_initial_preparation(marc_record, legacy_ids)
|
|
115
|
-
for marc_field in marc_record:
|
|
116
|
-
self.report_marc_stats(marc_field, bad_tags, legacy_ids, ignored_subsequent_fields)
|
|
117
|
-
if marc_field.tag not in ignored_subsequent_fields:
|
|
118
|
-
self.process_marc_field(
|
|
119
|
-
folio_authority,
|
|
120
|
-
marc_field,
|
|
121
|
-
ignored_subsequent_fields,
|
|
122
|
-
legacy_ids,
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
self.perform_additional_parsing(folio_authority)
|
|
126
|
-
clean_folio_authority = self.validate_required_properties(
|
|
127
|
-
"-".join(legacy_ids), folio_authority, self.schema, FOLIONamespaces.instances
|
|
128
|
-
)
|
|
129
|
-
self.dedupe_rec(clean_folio_authority)
|
|
130
|
-
marc_record.remove_fields(*list(bad_tags))
|
|
131
|
-
self.report_folio_mapping(clean_folio_authority, self.schema)
|
|
132
|
-
return [clean_folio_authority]
|
|
133
|
-
|
|
134
|
-
def perform_initial_preparation(self, marc_record: pymarc.Record, legacy_ids):
|
|
135
|
-
folio_authority = {}
|
|
136
|
-
folio_authority["id"] = str(
|
|
137
|
-
FolioUUID(
|
|
138
|
-
self.base_string_for_folio_uuid,
|
|
139
|
-
FOLIONamespaces.authorities,
|
|
140
|
-
str(legacy_ids[-1]),
|
|
141
|
-
)
|
|
142
|
-
)
|
|
143
|
-
HRIDHandler.handle_035_generation(
|
|
144
|
-
marc_record, legacy_ids, self.migration_report, False, False
|
|
145
|
-
)
|
|
146
|
-
self.map_source_file_and_natural_id(marc_record, folio_authority)
|
|
147
|
-
self.handle_leader_17(marc_record, legacy_ids)
|
|
148
|
-
return folio_authority
|
|
149
|
-
|
|
150
|
-
def map_source_file_and_natural_id(self, marc_record, folio_authority):
|
|
151
|
-
"""Implement source file and natural ID mappings according to MODDICORE-283"""
|
|
152
|
-
match_prefix_patt = re.compile("^[A-Za-z]+")
|
|
153
|
-
natural_id = None
|
|
154
|
-
source_file_id = None
|
|
155
|
-
has_010 = marc_record.get("010")
|
|
156
|
-
if has_010 and (has_010a := has_010.get_subfields("a")):
|
|
157
|
-
for a_subfield in has_010a:
|
|
158
|
-
natural_id_prefix = match_prefix_patt.match(a_subfield)
|
|
159
|
-
if natural_id_prefix and (
|
|
160
|
-
source_file := self.source_file_mapping.get(natural_id_prefix.group(0), None)
|
|
161
|
-
):
|
|
162
|
-
natural_id = "".join(a_subfield.split())
|
|
163
|
-
source_file_id = source_file["id"]
|
|
164
|
-
self.migration_report.add_general_statistics(
|
|
165
|
-
i18n.t("naturalId mapped from %{fro}", fro="010$a")
|
|
166
|
-
)
|
|
167
|
-
self.migration_report.add(
|
|
168
|
-
"AuthoritySourceFileMapping",
|
|
169
|
-
f"{source_file['name']} -- {natural_id_prefix.group(0)} -- 010$a",
|
|
170
|
-
number=1,
|
|
171
|
-
)
|
|
172
|
-
break
|
|
173
|
-
if not source_file_id:
|
|
174
|
-
natural_id = "".join(marc_record["001"].data.split())
|
|
175
|
-
self.migration_report.add_general_statistics(
|
|
176
|
-
i18n.t("naturalId mapped from %{fro}", fro="001")
|
|
177
|
-
)
|
|
178
|
-
natural_id_prefix = match_prefix_patt.match(natural_id)
|
|
179
|
-
if natural_id_prefix:
|
|
180
|
-
if source_file := self.source_file_mapping.get(natural_id_prefix.group(0), None):
|
|
181
|
-
source_file_id = source_file["id"]
|
|
182
|
-
self.migration_report.add(
|
|
183
|
-
"AuthoritySourceFileMapping",
|
|
184
|
-
f"{source_file['name']} -- {natural_id_prefix.group(0)} -- 001",
|
|
185
|
-
number=1,
|
|
186
|
-
)
|
|
187
|
-
folio_authority["naturalId"] = natural_id
|
|
188
|
-
if source_file_id:
|
|
189
|
-
folio_authority["sourceFileId"] = source_file_id
|
|
190
|
-
|
|
191
|
-
def setup_source_file_mapping(self):
|
|
192
|
-
if self.folio_client.authority_source_files:
|
|
193
|
-
logging.info(
|
|
194
|
-
f"{len(self.folio_client.authority_source_files)} \tAuthority source files"
|
|
195
|
-
)
|
|
196
|
-
for source_file in self.folio_client.authority_source_files:
|
|
197
|
-
for sf_code in source_file.get("codes", []):
|
|
198
|
-
self.source_file_mapping[sf_code] = source_file
|
|
199
|
-
|
|
200
|
-
def handle_leader_17(self, marc_record, legacy_ids):
|
|
201
|
-
leader_17 = marc_record.leader[17] or "Empty"
|
|
202
|
-
self.migration_report.add(
|
|
203
|
-
"AuthorityEncodingLevel", i18n.t("Original value") + f": {leader_17}"
|
|
204
|
-
)
|
|
205
|
-
if leader_17 not in ["n", "o"]:
|
|
206
|
-
Helper.log_data_issue(
|
|
207
|
-
legacy_ids,
|
|
208
|
-
f"LDR pos. 17 is '{leader_17}'. Is this correct? Value has been changed to 'n'.",
|
|
209
|
-
marc_record.leader,
|
|
210
|
-
)
|
|
211
|
-
marc_record.leader = Leader(f"{marc_record.leader[:17]}n{marc_record.leader[18:]}")
|
|
212
|
-
self.migration_report.add(
|
|
213
|
-
"AuthorityEncodingLevel", i18n.t("Changed %{a} to %{b}", a=leader_17, b="n")
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
def perform_additional_parsing(
|
|
217
|
-
self,
|
|
218
|
-
folio_authority: dict,
|
|
219
|
-
) -> None:
|
|
220
|
-
"""Do stuff not easily captured by the mapping rules
|
|
221
|
-
|
|
222
|
-
Args:
|
|
223
|
-
folio_authority (dict): _description_
|
|
224
|
-
"""
|
|
225
|
-
folio_authority["source"] = "MARC"
|
|
226
|
-
|
|
227
|
-
def get_authority_json_schema(self, folio_client: FolioClient, library_configuration):
|
|
228
|
-
"""Fetches the JSON Schema for autorities"""
|
|
229
|
-
if library_configuration.folio_release.name.lower()[0] < "p":
|
|
230
|
-
schema = folio_client.get_from_github(
|
|
231
|
-
"folio-org", "mod-inventory-storage", "/ramls/authorities/authority.json"
|
|
232
|
-
)
|
|
233
|
-
else:
|
|
234
|
-
schema = folio_client.get_from_github(
|
|
235
|
-
"folio-org",
|
|
236
|
-
"mod-entities-links",
|
|
237
|
-
"/src/main/resources/swagger.api/schemas/authority-storage/authorityDto.yaml",
|
|
238
|
-
)
|
|
239
|
-
return schema
|
|
240
|
-
|
|
241
|
-
def wrap_up(self):
|
|
242
|
-
logging.info("Mapper wrapping up")
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from typing import Annotated
|
|
3
|
-
from typing import List
|
|
4
|
-
import i18n
|
|
5
|
-
|
|
6
|
-
from folio_uuid.folio_namespaces import FOLIONamespaces
|
|
7
|
-
from pydantic import Field
|
|
8
|
-
|
|
9
|
-
from folio_migration_tools.helper import Helper
|
|
10
|
-
from folio_migration_tools.library_configuration import FileDefinition
|
|
11
|
-
from folio_migration_tools.library_configuration import IlsFlavour
|
|
12
|
-
from folio_migration_tools.library_configuration import LibraryConfiguration
|
|
13
|
-
from folio_migration_tools.marc_rules_transformation.marc_file_processor import (
|
|
14
|
-
MarcFileProcessor,
|
|
15
|
-
)
|
|
16
|
-
from folio_migration_tools.marc_rules_transformation.rules_mapper_authorities import (
|
|
17
|
-
AuthorityMapper,
|
|
18
|
-
)
|
|
19
|
-
from folio_migration_tools.migration_tasks.migration_task_base import MigrationTaskBase
|
|
20
|
-
from folio_migration_tools.task_configuration import AbstractTaskConfiguration
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class AuthorityTransformer(MigrationTaskBase):
|
|
24
|
-
class TaskConfiguration(AbstractTaskConfiguration):
|
|
25
|
-
name: Annotated[
|
|
26
|
-
str,
|
|
27
|
-
Field(
|
|
28
|
-
description=(
|
|
29
|
-
"Name of this migration task. The name is being used to call the specific "
|
|
30
|
-
"task, and to distinguish tasks of similar types"
|
|
31
|
-
)
|
|
32
|
-
),
|
|
33
|
-
]
|
|
34
|
-
migration_task_type: Annotated[
|
|
35
|
-
str,
|
|
36
|
-
Field(
|
|
37
|
-
title="Migration task type",
|
|
38
|
-
description=("The type of migration task you want to perform"),
|
|
39
|
-
),
|
|
40
|
-
]
|
|
41
|
-
files: Annotated[
|
|
42
|
-
List[FileDefinition],
|
|
43
|
-
Field(
|
|
44
|
-
title="Source files", description=("List of MARC21 files with authority records")
|
|
45
|
-
),
|
|
46
|
-
]
|
|
47
|
-
ils_flavour: Annotated[
|
|
48
|
-
IlsFlavour,
|
|
49
|
-
Field(
|
|
50
|
-
title="ILS flavour", description="The type of ILS you are migrating records from."
|
|
51
|
-
),
|
|
52
|
-
]
|
|
53
|
-
tags_to_delete: Annotated[
|
|
54
|
-
List[str],
|
|
55
|
-
Field(
|
|
56
|
-
title="Tags to delete from MARC record",
|
|
57
|
-
description=(
|
|
58
|
-
"Tags in the incoming MARC authority that the process should remove "
|
|
59
|
-
"before adding them into FOLIO. These tags will be used in the "
|
|
60
|
-
"transformation before getting removed."
|
|
61
|
-
),
|
|
62
|
-
),
|
|
63
|
-
] = []
|
|
64
|
-
create_source_records: Annotated[
|
|
65
|
-
bool,
|
|
66
|
-
Field(
|
|
67
|
-
title="Create source records",
|
|
68
|
-
description=(
|
|
69
|
-
"Controls wheter or not to retain the MARC records in Source Record Storage."
|
|
70
|
-
),
|
|
71
|
-
),
|
|
72
|
-
] = True
|
|
73
|
-
|
|
74
|
-
@staticmethod
|
|
75
|
-
def get_object_type() -> FOLIONamespaces:
|
|
76
|
-
return FOLIONamespaces.authorities
|
|
77
|
-
|
|
78
|
-
def __init__(
|
|
79
|
-
self,
|
|
80
|
-
task_config: TaskConfiguration,
|
|
81
|
-
library_config: LibraryConfiguration,
|
|
82
|
-
use_logging: bool = True,
|
|
83
|
-
):
|
|
84
|
-
super().__init__(library_config, task_config, use_logging)
|
|
85
|
-
self.processor: MarcFileProcessor
|
|
86
|
-
self.check_source_files(
|
|
87
|
-
self.folder_structure.legacy_records_folder, self.task_configuration.files
|
|
88
|
-
)
|
|
89
|
-
self.mapper: AuthorityMapper = AuthorityMapper(
|
|
90
|
-
self.folio_client, library_config, task_config
|
|
91
|
-
)
|
|
92
|
-
self.auth_ids: set = set()
|
|
93
|
-
logging.info("Init done")
|
|
94
|
-
|
|
95
|
-
def do_work(self):
|
|
96
|
-
self.do_work_marc_transformer()
|
|
97
|
-
|
|
98
|
-
def wrap_up(self):
|
|
99
|
-
logging.info("Done. Transformer Wrapping up...")
|
|
100
|
-
self.extradata_writer.flush()
|
|
101
|
-
self.processor.wrap_up()
|
|
102
|
-
with open(self.folder_structure.migration_reports_file, "w+") as report_file:
|
|
103
|
-
self.mapper.migration_report.write_migration_report(
|
|
104
|
-
i18n.t("Authority records transformation report"),
|
|
105
|
-
report_file,
|
|
106
|
-
self.start_datetime,
|
|
107
|
-
)
|
|
108
|
-
Helper.print_mapping_report(
|
|
109
|
-
report_file,
|
|
110
|
-
self.mapper.parsed_records,
|
|
111
|
-
self.mapper.mapped_folio_fields,
|
|
112
|
-
self.mapper.mapped_legacy_fields,
|
|
113
|
-
)
|
|
114
|
-
logging.info(
|
|
115
|
-
"Done. Transformation report written to %s",
|
|
116
|
-
self.folder_structure.migration_reports_file.name,
|
|
117
|
-
)
|
|
118
|
-
self.clean_out_empty_logs()
|
|
File without changes
|
|
File without changes
|