folio-migration-tools 1.10.2__py3-none-any.whl → 1.10.3__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/__init__.py +10 -2
- folio_migration_tools/__main__.py +7 -0
- folio_migration_tools/circulation_helper.py +23 -8
- folio_migration_tools/colors.py +7 -0
- folio_migration_tools/config_file_load.py +7 -0
- folio_migration_tools/custom_dict.py +17 -0
- folio_migration_tools/custom_exceptions.py +40 -4
- folio_migration_tools/extradata_writer.py +12 -0
- folio_migration_tools/folder_structure.py +16 -0
- folio_migration_tools/helper.py +7 -0
- folio_migration_tools/holdings_helper.py +11 -5
- folio_migration_tools/i18n_config.py +6 -0
- folio_migration_tools/library_configuration.py +19 -5
- folio_migration_tools/mapper_base.py +15 -0
- folio_migration_tools/mapping_file_transformation/__init__.py +1 -0
- folio_migration_tools/mapping_file_transformation/courses_mapper.py +17 -0
- folio_migration_tools/mapping_file_transformation/holdings_mapper.py +19 -0
- folio_migration_tools/mapping_file_transformation/item_mapper.py +24 -0
- folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +18 -0
- folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +26 -9
- folio_migration_tools/mapping_file_transformation/notes_mapper.py +16 -0
- folio_migration_tools/mapping_file_transformation/order_mapper.py +40 -27
- folio_migration_tools/mapping_file_transformation/organization_mapper.py +40 -33
- folio_migration_tools/mapping_file_transformation/ref_data_mapping.py +17 -0
- folio_migration_tools/mapping_file_transformation/user_mapper.py +16 -0
- folio_migration_tools/marc_rules_transformation/__init__.py +1 -0
- folio_migration_tools/marc_rules_transformation/conditions.py +49 -36
- folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +9 -3
- folio_migration_tools/marc_rules_transformation/hrid_handler.py +16 -1
- folio_migration_tools/marc_rules_transformation/marc_file_processor.py +15 -1
- folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py +7 -0
- folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +35 -29
- folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +23 -18
- folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +46 -27
- folio_migration_tools/migration_report.py +14 -6
- folio_migration_tools/migration_tasks/__init__.py +2 -0
- folio_migration_tools/migration_tasks/batch_poster.py +34 -18
- folio_migration_tools/migration_tasks/bibs_transformer.py +16 -0
- folio_migration_tools/migration_tasks/courses_migrator.py +15 -0
- folio_migration_tools/migration_tasks/holdings_csv_transformer.py +18 -3
- folio_migration_tools/migration_tasks/holdings_marc_transformer.py +17 -0
- folio_migration_tools/migration_tasks/inventory_batch_poster.py +424 -0
- folio_migration_tools/migration_tasks/items_transformer.py +16 -0
- folio_migration_tools/migration_tasks/loans_migrator.py +17 -2
- folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +16 -0
- folio_migration_tools/migration_tasks/marc_import.py +407 -0
- folio_migration_tools/migration_tasks/migration_task_base.py +49 -17
- folio_migration_tools/migration_tasks/orders_transformer.py +16 -0
- folio_migration_tools/migration_tasks/organization_transformer.py +17 -2
- folio_migration_tools/migration_tasks/requests_migrator.py +15 -0
- folio_migration_tools/migration_tasks/reserves_migrator.py +15 -0
- folio_migration_tools/migration_tasks/user_importer.py +347 -0
- folio_migration_tools/migration_tasks/user_transformer.py +16 -0
- folio_migration_tools/task_configuration.py +7 -0
- folio_migration_tools/transaction_migration/__init__.py +1 -0
- folio_migration_tools/transaction_migration/legacy_loan.py +16 -0
- folio_migration_tools/transaction_migration/legacy_request.py +14 -0
- folio_migration_tools/transaction_migration/legacy_reserve.py +14 -0
- folio_migration_tools/transaction_migration/transaction_result.py +16 -0
- {folio_migration_tools-1.10.2.dist-info → folio_migration_tools-1.10.3.dist-info}/METADATA +1 -1
- folio_migration_tools-1.10.3.dist-info/RECORD +66 -0
- folio_migration_tools-1.10.2.dist-info/RECORD +0 -63
- {folio_migration_tools-1.10.2.dist-info → folio_migration_tools-1.10.3.dist-info}/WHEEL +0 -0
- {folio_migration_tools-1.10.2.dist-info → folio_migration_tools-1.10.3.dist-info}/entry_points.txt +0 -0
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
"""Mapper for transforming notes to FOLIO Notes format.
|
|
2
|
+
|
|
3
|
+
Provides the NotesMapper class for mapping legacy notes to FOLIO Notes records.
|
|
4
|
+
Handles note types, content, and object associations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
1
7
|
import logging
|
|
2
8
|
import i18n
|
|
3
9
|
|
|
@@ -20,6 +26,16 @@ class NotesMapper(MappingFileMapperBase):
|
|
|
20
26
|
object_type: FOLIONamespaces,
|
|
21
27
|
ignore_legacy_identifier: bool = False,
|
|
22
28
|
) -> None:
|
|
29
|
+
"""Initialize NotesMapper for handling note transformations.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
library_configuration (LibraryConfiguration): Library configuration.
|
|
33
|
+
task_configuration: Task configuration for note migration.
|
|
34
|
+
folio_client (FolioClient): FOLIO API client.
|
|
35
|
+
record_map (dict): Mapping configuration for note fields.
|
|
36
|
+
object_type (FOLIONamespaces): Type of object containing notes.
|
|
37
|
+
ignore_legacy_identifier (bool): Whether to ignore legacy identifiers.
|
|
38
|
+
"""
|
|
23
39
|
self.folio_client: FolioClient = folio_client
|
|
24
40
|
self.setup_notes_schema()
|
|
25
41
|
super().__init__(
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""Mapper for transforming order data to FOLIO Orders format.
|
|
2
|
+
|
|
3
|
+
Provides the OrderMapper class for mapping legacy purchase order data to FOLIO
|
|
4
|
+
Orders and PurchaseOrderLines. Handles composite orders with embedded lines,
|
|
5
|
+
acquisition units, fund distributions, and vendor references.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
import json
|
|
2
9
|
import logging
|
|
3
10
|
import os
|
|
@@ -41,6 +48,23 @@ class CompositeOrderMapper(MappingFileMapperBase):
|
|
|
41
48
|
funds_map,
|
|
42
49
|
funds_expense_class_map=None,
|
|
43
50
|
):
|
|
51
|
+
"""Initialize CompositeOrderMapper for purchase order transformations.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
folio_client (FolioClient): FOLIO API client.
|
|
55
|
+
library_configuration (LibraryConfiguration): Library configuration.
|
|
56
|
+
task_configuration: Task configuration for orders migration.
|
|
57
|
+
composite_order_map (dict): Mapping configuration for order fields.
|
|
58
|
+
organizations_id_map (dict): Mapping of legacy to FOLIO organizations.
|
|
59
|
+
instance_id_map (dict): Mapping of legacy to FOLIO instances.
|
|
60
|
+
acquisition_method_map: Mapping of legacy to FOLIO acquisition methods.
|
|
61
|
+
payment_status_map: Mapping of legacy to FOLIO payment statuses.
|
|
62
|
+
receipt_status_map: Mapping of legacy to FOLIO receipt statuses.
|
|
63
|
+
workflow_status_map: Mapping of legacy to FOLIO workflow statuses.
|
|
64
|
+
location_map: Mapping of legacy to FOLIO locations.
|
|
65
|
+
funds_map: Mapping of legacy to FOLIO funds.
|
|
66
|
+
funds_expense_class_map: Mapping for fund expense classes.
|
|
67
|
+
"""
|
|
44
68
|
# Get organization schema
|
|
45
69
|
self.composite_order_schema = CompositeOrderMapper.get_latest_acq_schemas_from_github(
|
|
46
70
|
"folio-org", "mod-orders", "mod-orders", "composite_purchase_order"
|
|
@@ -139,19 +163,16 @@ class CompositeOrderMapper(MappingFileMapperBase):
|
|
|
139
163
|
|
|
140
164
|
@staticmethod
|
|
141
165
|
def get_latest_acq_schemas_from_github(owner, repo, module, object):
|
|
142
|
-
"""
|
|
143
|
-
Given a repository owner, a repository, a module name and the name
|
|
144
|
-
of a FOLIO acquisition object, returns a schema for that object that
|
|
145
|
-
also includes the schemas of any other referenced acq objects.
|
|
166
|
+
"""Fetch acquisition object schema from GitHub with referenced schemas.
|
|
146
167
|
|
|
147
168
|
Args:
|
|
148
|
-
owner (
|
|
149
|
-
repo (
|
|
150
|
-
module (
|
|
151
|
-
object (
|
|
169
|
+
owner (str): GitHub repository owner.
|
|
170
|
+
repo (str): GitHub repository name.
|
|
171
|
+
module (str): Module name within the repository.
|
|
172
|
+
object (str): Object name whose schema is to be fetched.
|
|
152
173
|
|
|
153
174
|
Returns:
|
|
154
|
-
|
|
175
|
+
Dict: _description_
|
|
155
176
|
"""
|
|
156
177
|
try:
|
|
157
178
|
# Authenticate when calling GitHub, using an API key stored in .env
|
|
@@ -206,22 +227,18 @@ class CompositeOrderMapper(MappingFileMapperBase):
|
|
|
206
227
|
|
|
207
228
|
@staticmethod
|
|
208
229
|
def get_submodules_of_latest_release(owner, repo, github_headers):
|
|
209
|
-
"""
|
|
210
|
-
Given a repository owner and a repository, identifies the latest
|
|
211
|
-
release of the repository and returns the submodules associated with
|
|
212
|
-
this release.
|
|
230
|
+
"""Get submodules associated with the latest release of a repository.
|
|
213
231
|
|
|
214
232
|
Args:
|
|
215
|
-
owner (
|
|
216
|
-
repo (
|
|
217
|
-
github_headers (
|
|
233
|
+
owner (str): GitHub repository owner.
|
|
234
|
+
repo (str): GitHub repository name.
|
|
235
|
+
github_headers (dict): Headers to use for GitHub API requests.
|
|
218
236
|
|
|
219
237
|
Returns:
|
|
220
|
-
|
|
238
|
+
list: List of submodules associated with the latest release.
|
|
221
239
|
|
|
222
240
|
|
|
223
241
|
"""
|
|
224
|
-
|
|
225
242
|
github_path = "https://api.github.com/repos"
|
|
226
243
|
|
|
227
244
|
# Get metadata for the latest release
|
|
@@ -258,20 +275,16 @@ class CompositeOrderMapper(MappingFileMapperBase):
|
|
|
258
275
|
|
|
259
276
|
@staticmethod
|
|
260
277
|
def build_extended_object(object_schema, submodule_path, github_headers):
|
|
261
|
-
"""
|
|
262
|
-
Takes an object schema (for example an organization) and the path to a
|
|
263
|
-
submodule repository and returns the same schema with the full schemas
|
|
264
|
-
of subordinate objects (for example aliases).
|
|
278
|
+
"""Extend an object schema with full schemas of subordinate objects.
|
|
265
279
|
|
|
266
280
|
Args:
|
|
267
|
-
object_schema (
|
|
268
|
-
submodule_path (
|
|
269
|
-
github_headers (
|
|
281
|
+
object_schema (dict): The schema of the object to be extended.
|
|
282
|
+
submodule_path (str): The path to the submodule containing schemas.
|
|
283
|
+
github_headers (dict): Headers to use for GitHub API requests.
|
|
270
284
|
|
|
271
285
|
Returns:
|
|
272
|
-
|
|
286
|
+
dict: The extended object schema.
|
|
273
287
|
"""
|
|
274
|
-
|
|
275
288
|
supported_types = [
|
|
276
289
|
"string",
|
|
277
290
|
"boolean",
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""Mapper for transforming organization data to FOLIO Organizations format.
|
|
2
|
+
|
|
3
|
+
Provides the OrganizationMapper class for mapping legacy vendor/organization data
|
|
4
|
+
to FOLIO Organization records. Handles embedded interfaces, contacts, categories,
|
|
5
|
+
and extradata object creation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
import json
|
|
2
9
|
import logging
|
|
3
10
|
import os
|
|
@@ -30,6 +37,18 @@ class OrganizationMapper(MappingFileMapperBase):
|
|
|
30
37
|
email_categories_map,
|
|
31
38
|
phone_categories_map,
|
|
32
39
|
):
|
|
40
|
+
"""Initialize OrganizationMapper for organization transformations.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
folio_client (FolioClient): FOLIO API client.
|
|
44
|
+
library_configuration (LibraryConfiguration): Library configuration.
|
|
45
|
+
task_config: Task configuration for organizations migration.
|
|
46
|
+
organization_map (dict): Mapping configuration for organization fields.
|
|
47
|
+
organization_types_map: Mapping of legacy to FOLIO organization types.
|
|
48
|
+
address_categories_map: Mapping of legacy to FOLIO address categories.
|
|
49
|
+
email_categories_map: Mapping of legacy to FOLIO email categories.
|
|
50
|
+
phone_categories_map: Mapping of legacy to FOLIO phone categories.
|
|
51
|
+
"""
|
|
33
52
|
# Build composite organization schema
|
|
34
53
|
if os.environ.get("GITHUB_TOKEN"):
|
|
35
54
|
logging.info("Using GITHUB_TOKEN environment variable for GitHub API Access")
|
|
@@ -119,15 +138,14 @@ class OrganizationMapper(MappingFileMapperBase):
|
|
|
119
138
|
email_categories_map,
|
|
120
139
|
phone_categories_map,
|
|
121
140
|
):
|
|
122
|
-
"""
|
|
141
|
+
"""Set up reference data mappings for organization categories and types.
|
|
123
142
|
|
|
124
143
|
Args:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
144
|
+
organization_types_map (dict): Mapping for organization types.
|
|
145
|
+
address_categories_map (dict): Mapping for address categories.
|
|
146
|
+
email_categories_map (dict): Mapping for email categories.
|
|
147
|
+
phone_categories_map (dict): Mapping for phone categories.
|
|
129
148
|
"""
|
|
130
|
-
|
|
131
149
|
categories_shared_args = (
|
|
132
150
|
self.folio_client,
|
|
133
151
|
"/organizations-storage/categories",
|
|
@@ -169,19 +187,16 @@ class OrganizationMapper(MappingFileMapperBase):
|
|
|
169
187
|
|
|
170
188
|
@staticmethod
|
|
171
189
|
def get_latest_acq_schemas_from_github(owner, repo, module, object):
|
|
172
|
-
"""
|
|
173
|
-
Given a repository owner, a repository, a module name and the name
|
|
174
|
-
of a FOLIO acquisition object, returns a schema for that object that
|
|
175
|
-
also includes the schemas of any other referenced acq objects.
|
|
190
|
+
"""Fetch acquisition object schema from GitHub with referenced schemas.
|
|
176
191
|
|
|
177
192
|
Args:
|
|
178
|
-
owner (
|
|
179
|
-
repo (
|
|
180
|
-
module (
|
|
181
|
-
object (
|
|
193
|
+
owner (str): GitHub repository owner.
|
|
194
|
+
repo (str): GitHub repository name.
|
|
195
|
+
module (str): Module name within the repository.
|
|
196
|
+
object (str): Object name whose schema is to be fetched.
|
|
182
197
|
|
|
183
198
|
Returns:
|
|
184
|
-
|
|
199
|
+
dict: The extended object schema.
|
|
185
200
|
"""
|
|
186
201
|
try:
|
|
187
202
|
# Authenticate when calling GitHub, using an API key stored in .env
|
|
@@ -232,20 +247,16 @@ class OrganizationMapper(MappingFileMapperBase):
|
|
|
232
247
|
|
|
233
248
|
@staticmethod
|
|
234
249
|
def get_submodules_of_latest_release(owner, repo, github_headers):
|
|
235
|
-
"""
|
|
236
|
-
Given a repository owner and a repository, identifies the latest
|
|
237
|
-
release of the repository and returns the submodules associated with
|
|
238
|
-
this release.
|
|
250
|
+
"""Get submodules associated with the latest release of a repository.
|
|
239
251
|
|
|
240
252
|
Args:
|
|
241
|
-
owner (
|
|
242
|
-
repo (
|
|
243
|
-
github_headers (
|
|
253
|
+
owner (str): GitHub repository owner.
|
|
254
|
+
repo (str): GitHub repository name.
|
|
255
|
+
github_headers (dict): Headers to use for GitHub API requests.
|
|
244
256
|
|
|
245
257
|
Returns:
|
|
246
|
-
|
|
258
|
+
list: List of submodules associated with the latest release.
|
|
247
259
|
"""
|
|
248
|
-
|
|
249
260
|
github_path = "https://api.github.com/repos"
|
|
250
261
|
|
|
251
262
|
# Get metadata for the latest release
|
|
@@ -280,20 +291,16 @@ class OrganizationMapper(MappingFileMapperBase):
|
|
|
280
291
|
|
|
281
292
|
@staticmethod
|
|
282
293
|
def build_extended_object(object_schema, submodule_path, github_headers):
|
|
283
|
-
"""
|
|
284
|
-
Takes an object schema (for example an organization) and the path to a
|
|
285
|
-
submodule repository and returns the same schema with the full schemas
|
|
286
|
-
of subordinate objects (for example aliases).
|
|
294
|
+
"""Extend an object schema with full schemas of subordinate objects.
|
|
287
295
|
|
|
288
296
|
Args:
|
|
289
|
-
object_schema (
|
|
290
|
-
submodule_path (
|
|
291
|
-
github_headers (
|
|
297
|
+
object_schema (dict): The base object schema to extend.
|
|
298
|
+
submodule_path (str): Path to the submodule containing additional schemas.
|
|
299
|
+
github_headers (dict): Headers to use for GitHub API requests.
|
|
292
300
|
|
|
293
301
|
Returns:
|
|
294
|
-
|
|
302
|
+
dict: The extended object schema.
|
|
295
303
|
"""
|
|
296
|
-
|
|
297
304
|
supported_types = ["string", "boolean", "number", "integer", "text", "object", "array"]
|
|
298
305
|
|
|
299
306
|
try:
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""Reference data mapping utilities.
|
|
2
|
+
|
|
3
|
+
Provides the RefDataMapping class for mapping legacy reference data values to FOLIO
|
|
4
|
+
reference data UUIDs. Handles lookups in FOLIO, wildcard matching, and default values
|
|
5
|
+
for common reference data types like locations, material types, and patron groups.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
import json
|
|
2
9
|
import logging
|
|
3
10
|
import sys
|
|
@@ -17,6 +24,16 @@ class RefDataMapping(object):
|
|
|
17
24
|
key_type,
|
|
18
25
|
blurb_id,
|
|
19
26
|
):
|
|
27
|
+
"""Initialize RefDataMapping for reference data transformations.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
folio_client (FolioClient): FOLIO API client for fetching reference data.
|
|
31
|
+
ref_data_path: API path to reference data endpoint.
|
|
32
|
+
array_name: Name of the data array in the API response.
|
|
33
|
+
the_map: Mapping configuration for data transformation.
|
|
34
|
+
key_type: Type of key being mapped.
|
|
35
|
+
blurb_id: Identifier for blurbs related to this mapping.
|
|
36
|
+
"""
|
|
20
37
|
self.name = array_name
|
|
21
38
|
self.cache: dict = {}
|
|
22
39
|
self.blurb_id = blurb_id
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
"""Mapper for transforming user/patron data to FOLIO Users format.
|
|
2
|
+
|
|
3
|
+
Provides the UserMapper class for mapping legacy patron data to FOLIO User records
|
|
4
|
+
using configured mapping files.
|
|
5
|
+
"""
|
|
6
|
+
|
|
1
7
|
import csv
|
|
2
8
|
import json
|
|
3
9
|
import logging
|
|
@@ -31,6 +37,16 @@ class UserMapper(MappingFileMapperBase):
|
|
|
31
37
|
departments_mapping,
|
|
32
38
|
groups_map,
|
|
33
39
|
):
|
|
40
|
+
"""Initialize UserMapper for user transformations.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
folio_client (FolioClient): FOLIO API client.
|
|
44
|
+
task_config: Task configuration for users migration.
|
|
45
|
+
library_config: Library configuration.
|
|
46
|
+
user_map: Mapping configuration for user fields.
|
|
47
|
+
departments_mapping: Mapping of legacy to FOLIO departments.
|
|
48
|
+
groups_map: Mapping of legacy to FOLIO user groups.
|
|
49
|
+
"""
|
|
34
50
|
try:
|
|
35
51
|
user_schema = folio_client.get_from_github(
|
|
36
52
|
"folio-org", "mod-user-import", "/ramls/schemas/userdataimport.json"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""MARC record transformation using FOLIO mapping rules."""
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
"""MARC rules conditions processing.
|
|
2
|
+
|
|
3
|
+
A reimplementation of FOLIO's MARC transformation rules. Handles
|
|
4
|
+
evaluation of rule conditions including field presence, indicator values, subfield
|
|
5
|
+
patterns, and parameter validation. Supports complex boolean logic for controlling
|
|
6
|
+
when transformation rules should be applied.
|
|
7
|
+
"""
|
|
8
|
+
|
|
1
9
|
import logging
|
|
2
10
|
import re
|
|
3
11
|
import traceback
|
|
@@ -36,6 +44,15 @@ class Conditions:
|
|
|
36
44
|
folio_release: FolioRelease,
|
|
37
45
|
default_call_number_type_name="",
|
|
38
46
|
):
|
|
47
|
+
"""Initialize Conditions processor for MARC field transformation rules.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
folio (FolioClient): FOLIO API client.
|
|
51
|
+
mapper (RulesMapperBase): Base mapper for rules processing.
|
|
52
|
+
object_type: Type of FOLIO object being transformed.
|
|
53
|
+
folio_release (FolioRelease): FOLIO release version.
|
|
54
|
+
default_call_number_type_name (str): Default call number type name.
|
|
55
|
+
"""
|
|
39
56
|
self.filter_chars = r"[.,\/#!$%\^&\*;:{}=\-_`~()]"
|
|
40
57
|
self.filter_chars_dop = r"[.,\/#!$%\^&\*;:{}=\_`~()]"
|
|
41
58
|
self.folio_release: FolioRelease = folio_release
|
|
@@ -161,10 +178,11 @@ class Conditions:
|
|
|
161
178
|
return attr(legacy_id, value, parameter, marc_field)
|
|
162
179
|
|
|
163
180
|
def condition_trim_punctuation(self, legacy_id, value, parameter, marc_field: field.Field):
|
|
164
|
-
"""
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
181
|
+
"""Strip whitespace and trailing punctuation, preserving initials and hyphens.
|
|
182
|
+
|
|
183
|
+
Removes leading/trailing whitespace and trailing commas/periods, unless
|
|
184
|
+
the period is preceded by a single alpha character (eg. "John D.").
|
|
185
|
+
Also preserves any trailing "-" (eg. "1981-"). Introduced in Poppy.
|
|
168
186
|
"""
|
|
169
187
|
pattern1 = re.compile(r"^(.*?)\s.[.]$")
|
|
170
188
|
pattern2 = re.compile(r"^(.*?)\s.,[.]$")
|
|
@@ -314,7 +332,7 @@ class Conditions:
|
|
|
314
332
|
def condition_remove_prefix_by_indicator(
|
|
315
333
|
self, legacy_id, value, parameter, marc_field: field.Field
|
|
316
334
|
):
|
|
317
|
-
"""Returns the index title according to the rules"""
|
|
335
|
+
"""Returns the index title according to the rules."""
|
|
318
336
|
ind2 = marc_field.indicator2
|
|
319
337
|
reg_str = r"[\s:\/]{0,3}$"
|
|
320
338
|
if ind2 not in map(str, range(1, 9)):
|
|
@@ -759,12 +777,11 @@ class Conditions:
|
|
|
759
777
|
def condition_set_electronic_access_relations_id(
|
|
760
778
|
self, legacy_id, value, parameter, marc_field: field.Field
|
|
761
779
|
):
|
|
762
|
-
"""
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
HoldingsMarcTransformer task definition containing the name parameter.
|
|
780
|
+
"""Map electronic access relationship IDs with optional holdings-specific behavior.
|
|
781
|
+
|
|
782
|
+
For FOLIO holdings, provides an optional alternative mapping based on a name
|
|
783
|
+
parameter, bypassing the FOLIO MARC-to-Holdings mapping engine. Requires a
|
|
784
|
+
supplemental mapping rules file in the HoldingsMarcTransformer task definition.
|
|
768
785
|
"""
|
|
769
786
|
if self.object_type == "holdings" and "name" in parameter:
|
|
770
787
|
try:
|
|
@@ -808,7 +825,7 @@ class Conditions:
|
|
|
808
825
|
def condition_set_note_staff_only_via_indicator(
|
|
809
826
|
self, legacy_id, value, parameter, marc_field: field.Field
|
|
810
827
|
):
|
|
811
|
-
"""Returns true of false depending on the first indicator"""
|
|
828
|
+
"""Returns true of false depending on the first indicator."""
|
|
812
829
|
# https://www.loc.gov/marc/bibliographic/bd541.html
|
|
813
830
|
ind1 = marc_field.indicator1
|
|
814
831
|
self.mapper.migration_report.add(
|
|
@@ -869,11 +886,10 @@ class Conditions:
|
|
|
869
886
|
) from e
|
|
870
887
|
|
|
871
888
|
def condition_set_receipt_status(self, legacy_id, value, parameter, marc_field: field.Field):
|
|
872
|
-
"""
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
HoldingsMarcTransformer task definition.
|
|
889
|
+
"""Map receipt status from MARC 008 field.
|
|
890
|
+
|
|
891
|
+
Requires a supplemental mapping rules file in HoldingsMarcTransformer
|
|
892
|
+
as this condition is not available in FOLIO's MARC mapping engine.
|
|
877
893
|
"""
|
|
878
894
|
if len(value) < 7:
|
|
879
895
|
self.mapper.migration_report.add(
|
|
@@ -911,11 +927,10 @@ class Conditions:
|
|
|
911
927
|
def condition_set_acquisition_method(
|
|
912
928
|
self, legacy_id, value, parameter, marc_field: field.Field
|
|
913
929
|
):
|
|
914
|
-
"""
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
HoldingsMarcTransformer task definition.
|
|
930
|
+
"""Map acquisition method from MARC 008 field.
|
|
931
|
+
|
|
932
|
+
Requires a supplemental mapping rules file in HoldingsMarcTransformer
|
|
933
|
+
as this condition is not available in FOLIO's MARC mapping engine.
|
|
919
934
|
"""
|
|
920
935
|
if len(value) < 8:
|
|
921
936
|
self.mapper.migration_report.add(
|
|
@@ -953,11 +968,10 @@ class Conditions:
|
|
|
953
968
|
return ""
|
|
954
969
|
|
|
955
970
|
def condition_set_retention_policy(self, legacy_id, value, parameter, marc_field: field.Field):
|
|
956
|
-
"""
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
HoldingsMarcTransformer task definition.
|
|
971
|
+
"""Map retention policy from MARC 008 field.
|
|
972
|
+
|
|
973
|
+
Requires a supplemental mapping rules file in HoldingsMarcTransformer
|
|
974
|
+
as this condition is not available in FOLIO's MARC mapping engine.
|
|
961
975
|
"""
|
|
962
976
|
if len(value) < 13:
|
|
963
977
|
self.mapper.migration_report.add(
|
|
@@ -1037,11 +1051,11 @@ class Conditions:
|
|
|
1037
1051
|
return ""
|
|
1038
1052
|
|
|
1039
1053
|
def condition_set_ill_policy(self, legacy_id, value, parameter, marc_field: field.Field):
|
|
1054
|
+
"""Map ILL policy from MARC 008 field.
|
|
1055
|
+
|
|
1056
|
+
Requires a supplemental mapping rules file in HoldingsMarcTransformer
|
|
1057
|
+
as this condition is not available in FOLIO's MARC mapping engine.
|
|
1040
1058
|
"""
|
|
1041
|
-
This method maps the ILL policy based on the 008 field.
|
|
1042
|
-
This condition is not available in FOLIO's MARC mapping engine and
|
|
1043
|
-
will require use of a supplemental mapping rules file in the
|
|
1044
|
-
HoldingsMarcTransformer task definition."""
|
|
1045
1059
|
if len(value) < 21:
|
|
1046
1060
|
self.mapper.migration_report.add(
|
|
1047
1061
|
"ILLPolicyMapping", i18n.t("008 is too short") + f": {value}"
|
|
@@ -1077,11 +1091,10 @@ class Conditions:
|
|
|
1077
1091
|
def condition_set_digitization_policy(
|
|
1078
1092
|
self, legacy_id, value, parameter, marc_field: field.Field
|
|
1079
1093
|
):
|
|
1080
|
-
"""
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
HoldingsMarcTransformer task definition.
|
|
1094
|
+
"""Map digitization policy from MARC 008 field.
|
|
1095
|
+
|
|
1096
|
+
Requires a supplemental mapping rules file in HoldingsMarcTransformer
|
|
1097
|
+
as this condition is not available in FOLIO's MARC mapping engine.
|
|
1085
1098
|
"""
|
|
1086
1099
|
if len(value) < 22:
|
|
1087
1100
|
self.mapper.migration_report.add(
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""MARC holdings statements parser.
|
|
2
|
+
|
|
3
|
+
Parses MARC21 holdings statements from fields 853-855, 863-865, 866-868 and converts
|
|
4
|
+
them to FOLIO-compatible holdings statements. Handles enumeration, chronology, and
|
|
5
|
+
holdings notes with proper formatting and validation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
import calendar
|
|
2
9
|
import contextlib
|
|
3
10
|
import logging
|
|
@@ -20,7 +27,7 @@ class HoldingsStatementsParser:
|
|
|
20
27
|
legacy_ids: List[str],
|
|
21
28
|
dedupe_results: bool = True,
|
|
22
29
|
) -> dict:
|
|
23
|
-
"""_summary_
|
|
30
|
+
"""_summary_.
|
|
24
31
|
|
|
25
32
|
Args:
|
|
26
33
|
marc_record (Record): pymarc Record object
|
|
@@ -36,7 +43,6 @@ class HoldingsStatementsParser:
|
|
|
36
43
|
Returns:
|
|
37
44
|
dict: A dictionary containing parsed holdings statements and related information.
|
|
38
45
|
""" # noqa: E501
|
|
39
|
-
|
|
40
46
|
# Textual holdings statements
|
|
41
47
|
return_dict: dict = {"statements": [], "migration_report": [], "hlm_stmts": []}
|
|
42
48
|
HoldingsStatementsParser.get_textual_statements(
|
|
@@ -178,7 +184,7 @@ class HoldingsStatementsParser:
|
|
|
178
184
|
def get_textual_statements(
|
|
179
185
|
marc_record: Record, field_textual: str, return_dict: dict, legacy_ids: List[str]
|
|
180
186
|
):
|
|
181
|
-
"""Returns the textual statements from the relevant marc fields
|
|
187
|
+
"""Returns the textual statements from the relevant marc fields.
|
|
182
188
|
|
|
183
189
|
Args:
|
|
184
190
|
marc_record (Record): _description_
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""HRID (Human Readable ID) handling for MARC transformations.
|
|
2
|
+
|
|
3
|
+
Manages HRID generation and 001/003/035 field manipulation during MARC transformation.
|
|
4
|
+
Supports both FOLIO-generated HRIDs and preservation of legacy 001 fields as HRIDs.
|
|
5
|
+
Handles creation of 035 fields from previous 001/003 combinations.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
import json
|
|
2
9
|
import logging
|
|
3
10
|
from typing import Set
|
|
@@ -22,6 +29,14 @@ class HRIDHandler:
|
|
|
22
29
|
migration_report: MigrationReport,
|
|
23
30
|
deactivate035_from001: bool,
|
|
24
31
|
):
|
|
32
|
+
"""Initialize HRID handler for managing FOLIO Human-Readable IDs.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
folio_client (FolioClient): FOLIO API client.
|
|
36
|
+
handling (HridHandling): HRID handling configuration.
|
|
37
|
+
migration_report (MigrationReport): Report for tracking operations.
|
|
38
|
+
deactivate035_from001 (bool): Whether to deactivate 035 fields derived from 001.
|
|
39
|
+
"""
|
|
25
40
|
self.unique_001s: Set[str] = set()
|
|
26
41
|
self.deactivate035_from001: bool = deactivate035_from001
|
|
27
42
|
self.hrid_path = "/hrid-settings-storage/hrid-settings"
|
|
@@ -45,7 +60,7 @@ class HRIDHandler:
|
|
|
45
60
|
marc_record: Record,
|
|
46
61
|
legacy_ids: list[str],
|
|
47
62
|
) -> None:
|
|
48
|
-
"""Create HRID if not mapped. Add hrid as MARC record 001
|
|
63
|
+
"""Create HRID if not mapped. Add hrid as MARC record 001.
|
|
49
64
|
|
|
50
65
|
Args:
|
|
51
66
|
namespace (FOLIONamespaces): determening the type of hrid setting to update
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""MARC file processing orchestration.
|
|
2
|
+
|
|
3
|
+
Orchestrates the processing of MARC records through the transformation pipeline.
|
|
4
|
+
Handles record reading, validation, transformation via rules mappers, and output
|
|
5
|
+
writing. Manages error handling, progress reporting, and batch processing.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
import logging
|
|
2
9
|
import os
|
|
3
10
|
import sys
|
|
@@ -29,6 +36,13 @@ class MarcFileProcessor:
|
|
|
29
36
|
folder_structure: FolderStructure,
|
|
30
37
|
created_objects_file: TextIO,
|
|
31
38
|
):
|
|
39
|
+
"""Initialize MARC file processor for processing MARC records.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
mapper (RulesMapperBase): MARC rules mapper for transformations.
|
|
43
|
+
folder_structure (FolderStructure): Folder structure for file paths.
|
|
44
|
+
created_objects_file (TextIO): File handle for writing created objects.
|
|
45
|
+
"""
|
|
32
46
|
self.object_type: FOLIONamespaces = folder_structure.object_type
|
|
33
47
|
self.folder_structure: FolderStructure = folder_structure
|
|
34
48
|
self.mapper: RulesMapperBase = mapper
|
|
@@ -51,7 +65,7 @@ class MarcFileProcessor:
|
|
|
51
65
|
self.parent_hrids = {entity[1]: entity[2] for entity in mapper.parent_id_map.values()}
|
|
52
66
|
|
|
53
67
|
def process_record(self, idx: int, marc_record: Record, file_def: FileDefinition):
|
|
54
|
-
"""
|
|
68
|
+
"""Processes a marc holdings record and saves it.
|
|
55
69
|
|
|
56
70
|
Args:
|
|
57
71
|
idx (int): Index in file being parsed
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""MARC record reader wrapper.
|
|
2
|
+
|
|
3
|
+
Provides a wrapper around pymarc's MARCReader with enhanced error handling,
|
|
4
|
+
encoding detection, and record validation. Supports multiple MARC file formats
|
|
5
|
+
and handles corrupted records gracefully.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
import logging
|
|
2
9
|
import sys
|
|
3
10
|
from io import IOBase
|