folio-migration-tools 1.9.0rc1__py3-none-any.whl → 1.9.0rc3__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.
@@ -101,7 +101,7 @@ class HoldingsMapper(MappingFileMapperBase):
101
101
  if legacy_value.startswith("[") and len(legacy_value.split(",")) == 1:
102
102
  try:
103
103
  legacy_value = ast.literal_eval(str(legacy_value))[0]
104
- except SyntaxError:
104
+ except (SyntaxError, ValueError):
105
105
  return legacy_value
106
106
  return legacy_value
107
107
 
@@ -24,6 +24,7 @@ from folio_migration_tools.mapping_file_transformation.mapping_file_mapper_base
24
24
  from folio_migration_tools.mapping_file_transformation.ref_data_mapping import (
25
25
  RefDataMapping,
26
26
  )
27
+ from folio_migration_tools.task_configuration import AbstractTaskConfiguration
27
28
 
28
29
 
29
30
  class ItemMapper(MappingFileMapperBase):
@@ -42,6 +43,7 @@ class ItemMapper(MappingFileMapperBase):
42
43
  temporary_location_mapping,
43
44
  library_configuration: LibraryConfiguration,
44
45
  boundwith_relationship_map,
46
+ task_configuration: AbstractTaskConfiguration
45
47
  ):
46
48
  item_schema = folio_client.get_item_schema()
47
49
  super().__init__(
@@ -52,6 +54,7 @@ class ItemMapper(MappingFileMapperBase):
52
54
  FOLIONamespaces.items,
53
55
  library_configuration,
54
56
  )
57
+ self.task_configuration = task_configuration
55
58
  self.item_schema = self.folio_client.get_item_schema()
56
59
  self.items_map = items_map
57
60
  self.holdings_id_map = holdings_id_map
@@ -90,6 +90,25 @@ class RulesMapperHoldings(RulesMapperBase):
90
90
  )
91
91
  self.mappings["852"] = new_852_mapping
92
92
 
93
+ def integrate_supplemental_mfhd_mappings(self, new_rules):
94
+ try:
95
+ self.mappings.update(new_rules)
96
+ except Exception as e:
97
+ raise TransformationProcessError(
98
+ "",
99
+ "Failed to integrate supplemental mfhd mappings",
100
+ str(e),
101
+ )
102
+
103
+ def prep_852_notes(self, marc_record: Record):
104
+ for field in marc_record.get_fields("852"):
105
+ new_952 = Field(
106
+ tag="952",
107
+ indicators=["f", "f"],
108
+ subfields=field.subfields
109
+ )
110
+ marc_record.add_ordered_field(new_952)
111
+
93
112
  def parse_record(
94
113
  self, marc_record: Record, file_def: FileDefinition, legacy_ids: List[str]
95
114
  ) -> list[dict]:
@@ -111,7 +130,7 @@ class RulesMapperHoldings(RulesMapperBase):
111
130
 
112
131
  self.print_progress()
113
132
  folio_holding = self.perform_initial_preparation(marc_record, legacy_ids)
114
-
133
+ self.prep_852_notes(marc_record)
115
134
  self.migration_report.add("RecordStatus", marc_record.leader[5])
116
135
  ignored_subsequent_fields: set = set()
117
136
  num_852s = 0
@@ -50,46 +50,84 @@ class BatchPoster(MigrationTaskBase):
50
50
  """
51
51
 
52
52
  class TaskConfiguration(AbstractTaskConfiguration):
53
- name: str
54
- migration_task_type: str
55
- object_type: str
56
- files: List[FileDefinition]
57
- batch_size: int
53
+ name: Annotated[
54
+ str,
55
+ Field(
56
+ title="Task name",
57
+ description="The name of the task",
58
+ ),
59
+ ]
60
+ migration_task_type: Annotated[
61
+ str,
62
+ Field(
63
+ title="Migration task type",
64
+ description="The type of migration task",
65
+ ),
66
+ ]
67
+ object_type: Annotated[
68
+ str,
69
+ Field(
70
+ title="Object type",
71
+ description=(
72
+ "The type of object being migrated"
73
+ "Examples of possible values: "
74
+ "'Extradata', 'SRS', Instances', 'Holdings', 'Items'"
75
+ ),
76
+ ),
77
+ ]
78
+ files: Annotated[
79
+ List[FileDefinition],
80
+ Field(
81
+ title="List of files",
82
+ description="List of files to be processed",
83
+ ),
84
+ ]
85
+ batch_size: Annotated[
86
+ int,
87
+ Field(
88
+ title="Batch size",
89
+ description="The batch size for processing files",
90
+ ),
91
+ ]
58
92
  rerun_failed_records: Annotated[
59
93
  bool,
60
94
  Field(
95
+ title="Rerun failed records",
61
96
  description=(
62
- "Toggles whether or not BatchPoster should try to rerun failed batches or "
63
- "just leave the failing records on disk."
64
- )
97
+ "Toggles whether or not BatchPoster should try to rerun "
98
+ "failed batches or just leave the failing records on disk."
99
+ ),
65
100
  ),
66
101
  ] = True
67
102
  use_safe_inventory_endpoints: Annotated[
68
103
  bool,
69
104
  Field(
105
+ title="Use safe inventory endpoints",
70
106
  description=(
71
- "Toggles the use of the safe/unsafe Inventory storage endpoints. "
72
- "Unsafe circumvents the Optimistic locking in FOLIO. Defaults to "
73
- "True (using the 'safe' options)"
74
- )
107
+ "Toggles the use of the safe/unsafe Inventory storage "
108
+ "endpoints. Unsafe circumvents the Optimistic locking "
109
+ "in FOLIO. Defaults to True (using the 'safe' options)"
110
+ ),
75
111
  ),
76
112
  ] = True
77
113
  extradata_endpoints: Annotated[
78
114
  dict,
79
115
  Field(
116
+ title="Extradata endpoints",
80
117
  description=(
81
118
  "A dictionary of extradata endpoints. "
82
119
  "The key is the object type and the value is the endpoint"
83
- )
120
+ ),
84
121
  ),
85
122
  ] = {}
86
123
  upsert: Annotated[
87
124
  bool,
88
125
  Field(
126
+ title="Upsert",
89
127
  description=(
90
- "Toggles whether or not to use the upsert feature of the Inventory storage "
91
- "endpoints. Defaults to False"
92
- )
128
+ "Toggles whether or not to use the upsert feature "
129
+ "of the Inventory storage endpoints. Defaults to False"
130
+ ),
93
131
  ),
94
132
  ] = False
95
133
 
@@ -188,9 +226,10 @@ class BatchPoster(MigrationTaskBase):
188
226
 
189
227
  except Exception as ee:
190
228
  if "idx" in locals() and self.task_configuration.files[idx:]:
191
- for file in self.task_configuration.files[idx:]:
229
+ for file_def in self.task_configuration.files[idx:]:
230
+ path = self.folder_structure.results_folder / file_def.file_name
192
231
  try:
193
- with open(file, "r") as failed_file:
232
+ with open(path, "r") as failed_file:
194
233
  failed_file.seek(self.processed)
195
234
  failed_recs_file.write(failed_file.read())
196
235
  self.processed = 0
@@ -1,5 +1,7 @@
1
1
  '''Main "script."'''
2
+
2
3
  import csv
4
+ import json
3
5
  import logging
4
6
  from typing import Annotated, List
5
7
 
@@ -42,7 +44,8 @@ class HoldingsMarcTransformer(MigrationTaskBase):
42
44
  files: Annotated[
43
45
  List[FileDefinition],
44
46
  Field(
45
- title="Source files", description=("List of MARC21 files with holdings records")
47
+ title="Source files",
48
+ description=("List of MARC21 files with holdings records"),
46
49
  ),
47
50
  ]
48
51
  hrid_handling: Annotated[
@@ -154,6 +157,13 @@ class HoldingsMarcTransformer(MigrationTaskBase):
154
157
  description="The UUID of the Holdings type that will be used for unmapped values",
155
158
  ),
156
159
  ]
160
+ supplemental_mfhd_mapping_rules_file: Annotated[
161
+ str,
162
+ Field(
163
+ title="Supplemental MFHD mapping rules file",
164
+ description="The name of the file in the mapping_files directory containing supplemental MFHD mapping rules",
165
+ ),
166
+ ] = ""
157
167
 
158
168
  @staticmethod
159
169
  def get_object_type() -> FOLIONamespaces:
@@ -204,11 +214,13 @@ class HoldingsMarcTransformer(MigrationTaskBase):
204
214
  csv.DictReader(boundwith_relationship_file, dialect="tsv")
205
215
  )
206
216
  logging.info(
207
- "Rows in Bound with relationship map: %s", len(self.boundwith_relationship_map)
217
+ "Rows in Bound with relationship map: %s",
218
+ len(self.boundwith_relationship_map),
208
219
  )
209
220
 
210
221
  location_map_path = (
211
- self.folder_structure.mapping_files_folder / self.task_config.location_map_file_name
222
+ self.folder_structure.mapping_files_folder
223
+ / self.task_config.location_map_file_name
212
224
  )
213
225
  with open(location_map_path) as location_map_file:
214
226
  self.location_map = list(csv.DictReader(location_map_file, dialect="tsv"))
@@ -217,7 +229,9 @@ class HoldingsMarcTransformer(MigrationTaskBase):
217
229
  self.check_source_files(
218
230
  self.folder_structure.legacy_records_folder, self.task_config.files
219
231
  )
220
- self.instance_id_map = self.load_id_map(self.folder_structure.instance_id_map_path, True)
232
+ self.instance_id_map = self.load_id_map(
233
+ self.folder_structure.instance_id_map_path, True
234
+ )
221
235
  self.mapper = RulesMapperHoldings(
222
236
  self.folio_client,
223
237
  self.location_map,
@@ -226,6 +240,7 @@ class HoldingsMarcTransformer(MigrationTaskBase):
226
240
  self.instance_id_map,
227
241
  self.boundwith_relationship_map,
228
242
  )
243
+ self.add_supplemental_mfhd_mappings()
229
244
  if (
230
245
  self.task_configuration.reset_hrid_settings
231
246
  and self.task_configuration.update_hrid_settings
@@ -234,6 +249,33 @@ class HoldingsMarcTransformer(MigrationTaskBase):
234
249
  logging.info("%s Instance ids in map", len(self.instance_id_map))
235
250
  logging.info("Init done")
236
251
 
252
+ def add_supplemental_mfhd_mappings(self):
253
+ if self.task_config.supplemental_mfhd_mapping_rules_file:
254
+ try:
255
+ with open(
256
+ (
257
+ self.folder_structure.mapping_files_folder
258
+ / self.task_config.supplemental_mfhd_mapping_rules_file
259
+ ),
260
+ "r",
261
+ ) as new_rules_file:
262
+ new_rules = json.load(new_rules_file)
263
+ if not isinstance(new_rules, dict):
264
+ raise TransformationProcessError(
265
+ "",
266
+ "Supplemental MFHD mapping rules file must contain a dictionary",
267
+ json.dumps(new_rules),
268
+ )
269
+ except FileNotFoundError:
270
+ raise TransformationProcessError(
271
+ "",
272
+ "Provided supplemental MFHD mapping rules file not found",
273
+ self.task_config.supplemental_mfhd_mapping_rules_file,
274
+ )
275
+ else:
276
+ new_rules = {}
277
+ self.mapper.integrate_supplemental_mfhd_mappings(new_rules)
278
+
237
279
  def do_work(self):
238
280
  self.do_work_marc_transformer()
239
281
 
@@ -200,6 +200,7 @@ class ItemsTransformer(MigrationTaskBase):
200
200
  temporary_location_mapping,
201
201
  self.library_configuration,
202
202
  self.boundwith_relationship_map,
203
+ self.task_configuration
203
204
  )
204
205
  if (
205
206
  self.task_configuration.reset_hrid_settings
@@ -16,8 +16,8 @@ class AbstractTaskConfiguration(BaseModel):
16
16
  Field(
17
17
  title="ECS tenant ID",
18
18
  description=(
19
- "The tenant ID to use when making requests to FOLIO APIs for this task, if ",
20
- "different from library configuration",
19
+ "The tenant ID to use when making requests to FOLIO APIs "
20
+ "for this task, if different from library configuration",
21
21
  ),
22
22
  ),
23
23
  ] = ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: folio_migration_tools
3
- Version: 1.9.0rc1
3
+ Version: 1.9.0rc3
4
4
  Summary: A tool allowing you to migrate data from legacy ILS:s (Library systems) into FOLIO LSP
5
5
  License: MIT
6
6
  Keywords: FOLIO,ILS,LSP,Library Systems,MARC21,Library data
@@ -14,8 +14,8 @@ folio_migration_tools/library_configuration.py,sha256=JE23VSUKDeCxzj_fOeQwkXF4fw
14
14
  folio_migration_tools/mapper_base.py,sha256=4rtZxmWp1qaAIG2awiJ3RElPM9IVA-n8-Qzzs0R31qc,20317
15
15
  folio_migration_tools/mapping_file_transformation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  folio_migration_tools/mapping_file_transformation/courses_mapper.py,sha256=mJQxxeTn1bCYb2zwFYyXJ6EGZpJ0DsmwOY3nED7D_gQ,8091
17
- folio_migration_tools/mapping_file_transformation/holdings_mapper.py,sha256=GI9xnN74EsUMAshXKNJ6p9bGPdLtK0PCXqbB3nIxrC8,7207
18
- folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=RR8eqbHaGrwtYl2HIouIfiS5B52mErD7eeOMhj_L2NU,10436
17
+ folio_migration_tools/mapping_file_transformation/holdings_mapper.py,sha256=nJS-xx1LszvbYfw0qdTUHX9xXHlxS7wP5mYmixFMh8A,7221
18
+ folio_migration_tools/mapping_file_transformation/item_mapper.py,sha256=CWKpve0UdppztCd5ex1dz47g78mTqKkgiij1HEsGMC8,10622
19
19
  folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py,sha256=nCkqbxaDHKxMuqQHh_afxQp48YrVD-SeCZ0L1iGvnkk,13402
20
20
  folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py,sha256=RacwSOP6r6i28EOywaepq5K5FimD8Ld5MlBo89FYO7c,37963
21
21
  folio_migration_tools/mapping_file_transformation/notes_mapper.py,sha256=auLQZqa4rSJo_MIV4Lc5-LG8RcBpp2bnKH243qNYq_0,3470
@@ -33,16 +33,16 @@ folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py,sha256=9A
33
33
  folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py,sha256=GFw8j9UtCxnUdLShmPzJa1MpCK8a0NkQIN5C3jyouRs,9604
34
34
  folio_migration_tools/marc_rules_transformation/rules_mapper_base.py,sha256=WWSJgYvF9LeY8vh-BtQi7Fm3J-cowUJKWa0Wk2Ge7fc,39358
35
35
  folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py,sha256=ckVeysbpW9s19pmHvogdRFOCouzz17Y6oKJD0_QfQAk,28924
36
- folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=EBxf9Qh5Y0eDOmqYssWfaizxafiXSYDFzWmCuPtdG-8,18226
36
+ folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py,sha256=k7QDWt-q3w2HecvjNUy2BeAaGe_FUL5gkx3iZv0j_Uk,18894
37
37
  folio_migration_tools/migration_report.py,sha256=BkRspM1hwTBnWeqsHamf7yVEofzLj560Q-9G--O00hw,4258
38
38
  folio_migration_tools/migration_tasks/__init__.py,sha256=ZkbY_yGyB84Ke8OMlYUzyyBj4cxxNrhMTwQlu_GbdDs,211
39
39
  folio_migration_tools/migration_tasks/authority_transformer.py,sha256=AoXg9s-GLO3yEEDCrQV7hc4YVXxwxsdxDdpj1zhHydE,4251
40
- folio_migration_tools/migration_tasks/batch_poster.py,sha256=6-PMMvhdoFbydIGeN1duHcoHMEFe4ePGzMX6tP5gxSs,30729
40
+ folio_migration_tools/migration_tasks/batch_poster.py,sha256=3A0_NdM9uvzZqU92R7WxuiDVdhbneOErqAUEb1-WR_w,32008
41
41
  folio_migration_tools/migration_tasks/bibs_transformer.py,sha256=XzlPo-0uuugJA4SM80xOlOj5nDK6OMDXFnAYg80hOBc,7791
42
42
  folio_migration_tools/migration_tasks/courses_migrator.py,sha256=dQerp97P3r7wmxK3Ovg6AriO6K_nTr6vA8RKj_XBEt4,5728
43
43
  folio_migration_tools/migration_tasks/holdings_csv_transformer.py,sha256=Hwr4YjgNIQpi2N-x8eq-mmRpXAyxYylQjpYubm03-ec,19668
44
- folio_migration_tools/migration_tasks/holdings_marc_transformer.py,sha256=yN0a8YVNx2P6NswxSylTca0MmNk1shze3PyKXv9JJIw,9547
45
- folio_migration_tools/migration_tasks/items_transformer.py,sha256=S3RZDKL8lQbO6V8RWzzV_aB_L8fjoNF78DTi9hnKpH4,15350
44
+ folio_migration_tools/migration_tasks/holdings_marc_transformer.py,sha256=8dtrhxyA9hbISISzpvMJGYaMaDbtZ1MOZeoJJF5lk24,11164
45
+ folio_migration_tools/migration_tasks/items_transformer.py,sha256=vcBEkH4znw3JU9rgekCXKoHiUXDj9QEZWvhoOtbusOc,15386
46
46
  folio_migration_tools/migration_tasks/loans_migrator.py,sha256=PCjr_bC2ixhPPk_D54m7B871_bQObn5oP_Sow3ocg54,33238
47
47
  folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py,sha256=CnmlTge7nChUJ10EiUkriQtJlVxWqglgfhjgneh2_yM,7247
48
48
  folio_migration_tools/migration_tasks/migration_task_base.py,sha256=5vVkBqUvCGuGPUyWlnKsLCFtgOQzq4jjBK_TBUHs7BE,13742
@@ -51,7 +51,7 @@ folio_migration_tools/migration_tasks/organization_transformer.py,sha256=kHxftiR
51
51
  folio_migration_tools/migration_tasks/requests_migrator.py,sha256=8gbgHMca6hxAo9zUC6u3Xh_Zg0K9tiS3UDBaGdE5sSs,13302
52
52
  folio_migration_tools/migration_tasks/reserves_migrator.py,sha256=rZzC_HwsjqTrnVAGPFgYuMwgZsjfLsyY6f6bhBRtBr0,9206
53
53
  folio_migration_tools/migration_tasks/user_transformer.py,sha256=WkWb7E03OIpq8s2jasCTPdevRoGcaUrlkTwBi0bTrys,10674
54
- folio_migration_tools/task_configuration.py,sha256=K88TCKz44uk3jiUxFS_VmCYcwr_LV6Wu9jV_p00-Lec,633
54
+ folio_migration_tools/task_configuration.py,sha256=C5-OQtZLH7b4lVeyj5v8OXsqKNN4tzfp9F3b4vhthN4,632
55
55
  folio_migration_tools/test_infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
56
  folio_migration_tools/test_infrastructure/mocked_classes.py,sha256=rNes6UlRqIWGwPurfiQK97IvgB5OPwnZTbv1T28jHzk,9150
57
57
  folio_migration_tools/transaction_migration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -60,8 +60,8 @@ folio_migration_tools/transaction_migration/legacy_request.py,sha256=1ulyFzPQw_I
60
60
  folio_migration_tools/transaction_migration/legacy_reserve.py,sha256=rZVtiMBYnt6aI0WxAwPN8fML_MKEUSUYsadCKPTeB4E,1839
61
61
  folio_migration_tools/transaction_migration/transaction_result.py,sha256=cTdCN0BnlI9_ZJB2Z3Fdkl9gpymIi-9mGZsRFlQcmDk,656
62
62
  folio_migration_tools/translations/en.json,sha256=HOVpkb_T-SN_x0NpDp8gyvV1hMLCui3SsG7ByyIv0OU,38669
63
- folio_migration_tools-1.9.0rc1.dist-info/LICENSE,sha256=PhIEkitVi3ejgq56tt6sWoJIG_zmv82cjjd_aYPPGdI,1072
64
- folio_migration_tools-1.9.0rc1.dist-info/METADATA,sha256=QxHgnFjxkklcsK5gVrIK7tEFKyk5qodSNa6V_cQbP7E,7415
65
- folio_migration_tools-1.9.0rc1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
66
- folio_migration_tools-1.9.0rc1.dist-info/entry_points.txt,sha256=Hbe-HjqMcU8FwVshVIkeWyZd9XwgT1CCMNf06EpHQu8,77
67
- folio_migration_tools-1.9.0rc1.dist-info/RECORD,,
63
+ folio_migration_tools-1.9.0rc3.dist-info/LICENSE,sha256=PhIEkitVi3ejgq56tt6sWoJIG_zmv82cjjd_aYPPGdI,1072
64
+ folio_migration_tools-1.9.0rc3.dist-info/METADATA,sha256=kBR49fcEK3g7hWDFN_7Z2VnlB1X_cDaFip0ZR8FDcTY,7415
65
+ folio_migration_tools-1.9.0rc3.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
66
+ folio_migration_tools-1.9.0rc3.dist-info/entry_points.txt,sha256=Hbe-HjqMcU8FwVshVIkeWyZd9XwgT1CCMNf06EpHQu8,77
67
+ folio_migration_tools-1.9.0rc3.dist-info/RECORD,,