folio-migration-tools 1.9.0a6__tar.gz → 1.9.0a7__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.
Files changed (66) hide show
  1. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/PKG-INFO +1 -1
  2. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/pyproject.toml +1 -1
  3. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/__main__.py +14 -5
  4. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/library_configuration.py +1 -6
  5. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapper_base.py +1 -1
  6. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/batch_poster.py +30 -14
  7. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/loans_migrator.py +8 -29
  8. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/LICENSE +0 -0
  9. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/README.md +0 -0
  10. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/__init__.py +0 -0
  11. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/circulation_helper.py +0 -0
  12. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/colors.py +0 -0
  13. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/config_file_load.py +0 -0
  14. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/custom_dict.py +0 -0
  15. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/custom_exceptions.py +0 -0
  16. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/extradata_writer.py +0 -0
  17. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/folder_structure.py +0 -0
  18. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/helper.py +0 -0
  19. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/holdings_helper.py +0 -0
  20. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/i18n_config.py +0 -0
  21. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/__init__.py +0 -0
  22. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/courses_mapper.py +0 -0
  23. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/holdings_mapper.py +0 -0
  24. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/item_mapper.py +0 -0
  25. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/manual_fee_fines_mapper.py +0 -0
  26. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/mapping_file_mapper_base.py +0 -0
  27. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/notes_mapper.py +0 -0
  28. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/order_mapper.py +0 -0
  29. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/organization_mapper.py +0 -0
  30. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/ref_data_mapping.py +0 -0
  31. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/mapping_file_transformation/user_mapper.py +0 -0
  32. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/__init__.py +0 -0
  33. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/conditions.py +0 -0
  34. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/holdings_statementsparser.py +0 -0
  35. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/hrid_handler.py +0 -0
  36. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/loc_language_codes.xml +0 -0
  37. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/marc_file_processor.py +0 -0
  38. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/marc_reader_wrapper.py +0 -0
  39. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_authorities.py +0 -0
  40. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_base.py +0 -0
  41. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_bibs.py +0 -0
  42. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/marc_rules_transformation/rules_mapper_holdings.py +0 -0
  43. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_report.py +0 -0
  44. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/__init__.py +0 -0
  45. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/authority_transformer.py +0 -0
  46. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/bibs_transformer.py +0 -0
  47. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/courses_migrator.py +0 -0
  48. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/holdings_csv_transformer.py +0 -0
  49. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/holdings_marc_transformer.py +0 -0
  50. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/items_transformer.py +0 -0
  51. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/manual_fee_fines_transformer.py +0 -0
  52. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/migration_task_base.py +0 -0
  53. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/orders_transformer.py +0 -0
  54. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/organization_transformer.py +0 -0
  55. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/requests_migrator.py +0 -0
  56. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/reserves_migrator.py +0 -0
  57. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/migration_tasks/user_transformer.py +0 -0
  58. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/task_configuration.py +0 -0
  59. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/test_infrastructure/__init__.py +0 -0
  60. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/test_infrastructure/mocked_classes.py +0 -0
  61. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/transaction_migration/__init__.py +0 -0
  62. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/transaction_migration/legacy_loan.py +0 -0
  63. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/transaction_migration/legacy_request.py +0 -0
  64. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/transaction_migration/legacy_reserve.py +0 -0
  65. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/transaction_migration/transaction_result.py +0 -0
  66. {folio_migration_tools-1.9.0a6 → folio_migration_tools-1.9.0a7}/src/folio_migration_tools/translations/en.json +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: folio_migration_tools
3
- Version: 1.9.0a6
3
+ Version: 1.9.0a7
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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "folio_migration_tools"
3
- version = "1.9.0a6"
3
+ version = "1.9.0a7"
4
4
  description = "A tool allowing you to migrate data from legacy ILS:s (Library systems) into FOLIO LSP"
5
5
  authors = ["Theodor Tolstoy <github.teddes@tolstoy.se>", "Lisa Sjögren", "Brooks Travis", "Jeremy Nelson", "Clinton Bradford"]
6
6
  license = "MIT"
@@ -3,6 +3,7 @@ import logging
3
3
  import sys
4
4
  from os import environ
5
5
  from pathlib import Path
6
+ from sqlite3 import connect
6
7
 
7
8
  import httpx
8
9
  import humps
@@ -124,7 +125,8 @@ def main():
124
125
  except TransformationProcessError as tpe:
125
126
  logging.critical(tpe.message)
126
127
  print(f"\n{tpe.message}: {tpe.data_value}")
127
- sys.exit("Transformation Failure")
128
+ print("Task failure. Halting.")
129
+ sys.exit(1)
128
130
  logging.info("Work done. Shutting down")
129
131
  sys.exit(0)
130
132
  except json.decoder.JSONDecodeError as json_error:
@@ -148,10 +150,17 @@ def main():
148
150
  print("Halting")
149
151
  sys.exit("JSON Not Matching Spec")
150
152
  except httpx.HTTPError as connection_error:
151
- print(
152
- f"\nConnection Error when connecting to {connection_error.request.url}. "
153
- "Are you connectet to the Internet/VPN? Do you need to update DNS settings?"
154
- )
153
+ if hasattr(connection_error, "response"):
154
+ print(
155
+ f"\nHTTP Error when connecting to {connection_error.request.url}. "
156
+ f"Status code: {connection_error.response.status_code}. "
157
+ f"\nResponse: {connection_error.response.text}"
158
+ )
159
+ else:
160
+ print(
161
+ f"\nConnection Error when connecting to {connection_error.request.url}. "
162
+ "Are you connected to the Internet/VPN? Do you need to update DNS settings?"
163
+ )
155
164
  sys.exit("HTTP Not Connecting")
156
165
  except FileNotFoundError as fnf_error:
157
166
  print(f"\n{fnf_error.strerror}: {fnf_error.filename}")
@@ -62,14 +62,9 @@ class IlsFlavour(str, Enum):
62
62
 
63
63
 
64
64
  class FolioRelease(str, Enum):
65
- lotus = "lotus"
66
- morning_glory = "morning-glory"
67
- nolana = "nolana"
68
- orchid = "orchid"
69
- poppy = "poppy"
70
- quesnelia = "quesnelia"
71
65
  ramsons = "ramsons"
72
66
  sunflower = "sunflower"
67
+ trillium = "trillium"
73
68
 
74
69
 
75
70
  class LibraryConfiguration(BaseModel):
@@ -444,7 +444,7 @@ class MapperBase:
444
444
  except IndexError:
445
445
  if call_numbers:
446
446
  bound_with_holding["callNumber"] = call_numbers[0]
447
- except SyntaxError:
447
+ except (SyntaxError, ValueError):
448
448
  bound_with_holding["callNumber"] = call_number
449
449
  else:
450
450
  bound_with_holding["callNumber"] = call_number
@@ -5,6 +5,7 @@ import sys
5
5
  import time
6
6
  import traceback
7
7
  from datetime import datetime
8
+ from math import log
8
9
  from typing import Annotated, List
9
10
  from uuid import uuid4
10
11
 
@@ -136,12 +137,12 @@ class BatchPoster(MigrationTaskBase):
136
137
  def do_work(self):
137
138
  with self.folio_client.get_folio_http_client() as httpx_client:
138
139
  self.http_client = httpx_client
139
- try:
140
- batch = []
141
- if self.task_configuration.object_type == "SRS":
142
- self.create_snapshot()
143
- with open(self.folder_structure.failed_recs_path, "w") as failed_recs_file:
144
- for file_def in self.task_configuration.files:
140
+ with open(self.folder_structure.failed_recs_path, "w", encoding='utf-8') as failed_recs_file:
141
+ try:
142
+ batch = []
143
+ if self.task_configuration.object_type == "SRS":
144
+ self.create_snapshot()
145
+ for idx, file_def in enumerate(self.task_configuration.files):
145
146
  path = self.folder_structure.results_folder / file_def.file_name
146
147
  with open(path) as rows:
147
148
  logging.info("Running %s", path)
@@ -172,9 +173,8 @@ class BatchPoster(MigrationTaskBase):
172
173
  self.processed,
173
174
  failed_recs_file,
174
175
  )
175
- logging.critical("Halting %s", tpe)
176
- print(f"\n\t{tpe.message}")
177
- sys.exit(1)
176
+ batch = []
177
+ raise
178
178
  except TransformationRecordFailedError as exception:
179
179
  self.handle_generic_exception(
180
180
  exception,
@@ -184,7 +184,21 @@ class BatchPoster(MigrationTaskBase):
184
184
  failed_recs_file,
185
185
  )
186
186
  batch = []
187
-
187
+ except (FileNotFoundError, PermissionError) as ose:
188
+ logging.error("Error reading file: %s", ose)
189
+
190
+ except Exception as ee:
191
+ if "idx" in locals() and self.task_configuration.files[idx:]:
192
+ for file in self.task_configuration.files[idx:]:
193
+ try:
194
+ with open(file, "r") as failed_file:
195
+ failed_file.seek(self.processed)
196
+ failed_recs_file.write(failed_file.read())
197
+ self.processed = 0
198
+ except (FileNotFoundError, PermissionError) as ose:
199
+ logging.error("Error reading file: %s", ose)
200
+ raise ee
201
+ finally:
188
202
  if self.task_configuration.object_type != "Extradata" and any(batch):
189
203
  try:
190
204
  self.post_batch(batch, failed_recs_file, self.processed)
@@ -193,10 +207,8 @@ class BatchPoster(MigrationTaskBase):
193
207
  exception, last_row, batch, self.processed, failed_recs_file
194
208
  )
195
209
  logging.info("Done posting %s records. ", (self.processed))
196
- except Exception as ee:
197
- if self.task_configuration.object_type == "SRS":
198
- self.commit_snapshot()
199
- raise ee
210
+ if self.task_configuration.object_type == "SRS":
211
+ self.commit_snapshot()
200
212
 
201
213
  def post_record_batch(self, batch, failed_recs_file, row):
202
214
  json_rec = json.loads(row.split("\t")[-1])
@@ -339,6 +351,10 @@ class BatchPoster(MigrationTaskBase):
339
351
 
340
352
  def post_batch(self, batch, failed_recs_file, num_records, recursion_depth=0):
341
353
  response = self.do_post(batch)
354
+ if response.status_code == 401:
355
+ logging.error("Authorization failed (%s). Fetching new auth token...", response.text)
356
+ self.folio_client.login()
357
+ response = self.do_post(batch)
342
358
  if response.status_code == 201:
343
359
  logging.info(
344
360
  (
@@ -8,11 +8,11 @@ import traceback
8
8
  from datetime import datetime, timedelta
9
9
  from typing import Optional
10
10
  from urllib.error import HTTPError
11
+ from zoneinfo import ZoneInfo
11
12
 
12
13
  import i18n
13
14
  from dateutil import parser as du_parser
14
15
  from folio_uuid.folio_namespaces import FOLIONamespaces
15
- from zoneinfo import ZoneInfo
16
16
 
17
17
  from folio_migration_tools.circulation_helper import CirculationHelper
18
18
  from folio_migration_tools.helper import Helper
@@ -131,34 +131,13 @@ class LoansMigrator(MigrationTaskBase):
131
131
  logging.info("Init completed")
132
132
 
133
133
  def check_smtp_config(self):
134
- if self.library_configuration.folio_release.lower() == FolioRelease.morning_glory:
135
- logging.warn("DEPRECATED: Morning Glory support will be removed in a future release!")
136
- okapi_config_base_path = "/configurations/entries"
137
- okapi_config_query = "(module=={}%20and%20configName=={}%20and%20code=={})"
138
- okapi_config_limit = 1000
139
- okapi_config_module = "SMTP_SERVER"
140
- okapi_config_name = "smtp"
141
- okapi_config_code = "EMAIL_SMTP_HOST_DISABLED"
142
- smtp_config_path = (
143
- okapi_config_base_path
144
- + "?"
145
- + str(okapi_config_limit)
146
- + "&query="
147
- + okapi_config_query.format(
148
- okapi_config_module, okapi_config_name, okapi_config_code
149
- )
150
- )
151
- smtp_config_disabled = self.folio_client.folio_get_single_object(smtp_config_path)[
152
- "configs"
153
- ]
154
- else:
155
- try:
156
- smtp_config = self.folio_client.folio_get_single_object("/smtp-configuration")[
157
- "smtpConfigurations"
158
- ][0]
159
- smtp_config_disabled = "disabled" in smtp_config["host"].lower()
160
- except IndexError:
161
- smtp_config_disabled = True
134
+ try:
135
+ smtp_config = self.folio_client.folio_get_single_object("/smtp-configuration")[
136
+ "smtpConfigurations"
137
+ ][0]
138
+ smtp_config_disabled = "disabled" in smtp_config["host"].lower()
139
+ except IndexError:
140
+ smtp_config_disabled = True
162
141
  print_smtp_warning()
163
142
  if not smtp_config_disabled:
164
143
  logging.warn("SMTP connection not disabled...")