folio-data-import 0.2.4__tar.gz → 0.2.5__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.

Potentially problematic release.


This version of folio-data-import might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: folio_data_import
3
- Version: 0.2.4
3
+ Version: 0.2.5
4
4
  Summary: A python module to interact with the data importing capabilities of the open-source FOLIO ILS
5
5
  License: MIT
6
6
  Author: Brooks Travis
@@ -19,7 +19,7 @@ Requires-Dist: flake8-bugbear (>=24.8.19,<25.0.0)
19
19
  Requires-Dist: flake8-docstrings (>=1.7.0,<2.0.0)
20
20
  Requires-Dist: flake8-isort (>=6.1.1,<7.0.0)
21
21
  Requires-Dist: folioclient (>=0.60.5,<0.61.0)
22
- Requires-Dist: httpx (>=0.23.0,<0.24.0)
22
+ Requires-Dist: httpx (>=0.27.2,<0.28.0)
23
23
  Requires-Dist: inquirer (>=3.4.0,<4.0.0)
24
24
  Requires-Dist: pyhumps (>=3.8.0,<4.0.0)
25
25
  Requires-Dist: pymarc (>=5.2.2,<6.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "folio_data_import"
3
- version = "0.2.4"
3
+ version = "0.2.5"
4
4
  description = "A python module to interact with the data importing capabilities of the open-source FOLIO ILS"
5
5
  authors = ["Brooks Travis <brooks.travis@gmail.com>"]
6
6
  license = "MIT"
@@ -15,7 +15,7 @@ folio-user-import = "folio_data_import.UserImport:sync_main"
15
15
  [tool.poetry.dependencies]
16
16
  python = "^3.9"
17
17
  folioclient = "^0.60.5"
18
- httpx = "^0.23.0"
18
+ httpx = "^0.27.2"
19
19
  pymarc = "^5.2.2"
20
20
  pyhumps = "^3.8.0"
21
21
  inquirer = "^3.4.0"
@@ -3,6 +3,7 @@ import asyncio
3
3
  import glob
4
4
  import io
5
5
  import os
6
+ import sys
6
7
  from typing import List
7
8
  import uuid
8
9
  from contextlib import ExitStack
@@ -30,6 +31,9 @@ except AttributeError:
30
31
  # The order in which the report summary should be displayed
31
32
  REPORT_SUMMARY_ORDERING = {"created": 0, "updated": 1, "discarded": 2, "error": 3}
32
33
 
34
+ # Set default timeout and backoff values for HTTP requests when retrying job status and final summary checks
35
+ RETRY_TIMEOUT_START = 1
36
+ RETRY_TIMEOUT_RETRY_FACTOR = 2
33
37
 
34
38
  class MARCImportJob:
35
39
  """
@@ -79,6 +83,7 @@ class MARCImportJob:
79
83
  self.import_profile_name = import_profile_name
80
84
  self.batch_size = batch_size
81
85
  self.batch_delay = batch_delay
86
+ self.current_retry_timeout = None
82
87
 
83
88
  async def do_work(self) -> None:
84
89
  """
@@ -148,10 +153,23 @@ class MARCImportJob:
148
153
  Raises:
149
154
  IndexError: If the job execution with the specified ID is not found.
150
155
  """
151
- job_status = self.folio_client.folio_get(
152
- "/metadata-provider/jobExecutions?statusNot=DISCARDED&uiStatusAny"
153
- "=PREPARING_FOR_PREVIEW&uiStatusAny=READY_FOR_PREVIEW&uiStatusAny=RUNNING&limit=50"
154
- )
156
+ try:
157
+ self.current_retry_timeout = (
158
+ self.current_retry_timeout * RETRY_TIMEOUT_RETRY_FACTOR
159
+ ) if self.current_retry_timeout else RETRY_TIMEOUT_START
160
+ job_status = self.folio_client.folio_get(
161
+ "/metadata-provider/jobExecutions?statusNot=DISCARDED&uiStatusAny"
162
+ "=PREPARING_FOR_PREVIEW&uiStatusAny=READY_FOR_PREVIEW&uiStatusAny=RUNNING&limit=50"
163
+ )
164
+ self.current_retry_timeout = None
165
+ except httpx.ConnectTimeout:
166
+ sleep(.25)
167
+ with httpx.Client(
168
+ timeout=self.current_retry_timeout,
169
+ verify=self.folio_client.ssl_verify
170
+ ) as temp_client:
171
+ self.folio_client.httpx_client = temp_client
172
+ return await self.get_job_status()
155
173
  try:
156
174
  status = [
157
175
  job for job in job_status["jobExecutions"] if job["id"] == self.job_id
@@ -392,9 +410,7 @@ class MARCImportJob:
392
410
  await self.get_job_status()
393
411
  sleep(1)
394
412
  if self.finished:
395
- job_summary = self.folio_client.folio_get(
396
- f"/metadata-provider/jobSummary/{self.job_id}"
397
- )
413
+ job_summary = await self.get_job_summary()
398
414
  job_summary.pop("jobExecutionId")
399
415
  job_summary.pop("totalErrors")
400
416
  columns = ["Summary"] + list(job_summary.keys())
@@ -425,6 +441,31 @@ class MARCImportJob:
425
441
  self.last_current = 0
426
442
  self.finished = False
427
443
 
444
+ async def get_job_summary(self) -> dict:
445
+ """
446
+ Retrieves the job summary for the current job execution.
447
+
448
+ Returns:
449
+ dict: The job summary for the current job execution.
450
+ """
451
+ try:
452
+ self.current_retry_timeout = (
453
+ self.current_retry_timeout * RETRY_TIMEOUT_RETRY_FACTOR
454
+ ) if self.current_retry_timeout else RETRY_TIMEOUT_START
455
+ job_summary = self.folio_client.folio_get(
456
+ f"/metadata-provider/jobSummary/{self.job_id}"
457
+ )
458
+ self.current_retry_timeout = None
459
+ except httpx.ReadTimeout: #
460
+ sleep(.25)
461
+ with httpx.Client(
462
+ timeout=self.current_retry_timeout,
463
+ verify=self.folio_client.ssl_verify
464
+ ) as temp_client:
465
+ self.folio_client.httpx_client = temp_client
466
+ return await self.get_job_summary()
467
+ return job_summary
468
+
428
469
 
429
470
  async def main() -> None:
430
471
  """
@@ -491,6 +532,17 @@ async def main() -> None:
491
532
  if args.member_tenant_id:
492
533
  folio_client.okapi_headers["x-okapi-tenant"] = args.member_tenant_id
493
534
 
535
+ if os.path.isabs(args.marc_file_path):
536
+ marc_files = [Path(x) for x in glob.glob(args.marc_file_path)]
537
+ else:
538
+ marc_files = list(Path("./").glob(args.marc_file_path))
539
+
540
+ if len(marc_files) == 0:
541
+ print(f"No files found matching {args.marc_file_path}. Exiting.")
542
+ sys.exit(1)
543
+ else:
544
+ print(marc_files)
545
+
494
546
  if not args.import_profile_name:
495
547
  import_profiles = folio_client.folio_get(
496
548
  "/data-import-profiles/jobProfiles",
@@ -511,8 +563,6 @@ async def main() -> None:
511
563
  ]
512
564
  answers = inquirer.prompt(questions)
513
565
  args.import_profile_name = answers["import_profile_name"]
514
- marc_files = [Path(x) for x in glob.glob(args.marc_file_path, root_dir="./")]
515
- print(marc_files)
516
566
  try:
517
567
  await MARCImportJob(
518
568
  folio_client,