BabelDOC 0.1.14__tar.gz → 0.1.16__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 (77) hide show
  1. {babeldoc-0.1.14 → babeldoc-0.1.16}/PKG-INFO +2 -1
  2. babeldoc-0.1.16/babeldoc/__init__.py +1 -0
  3. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/const.py +1 -1
  4. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/backend/pdf_creater.py +191 -2
  5. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/docvision/rpc_doclayout.py +56 -45
  6. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/main.py +1 -1
  7. {babeldoc-0.1.14 → babeldoc-0.1.16}/pyproject.toml +4 -3
  8. {babeldoc-0.1.14 → babeldoc-0.1.16}/uv.lock +12 -1
  9. babeldoc-0.1.14/babeldoc/__init__.py +0 -1
  10. {babeldoc-0.1.14 → babeldoc-0.1.16}/.cursorignore +0 -0
  11. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
  12. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
  13. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/dependabot.yml +0 -0
  14. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/labels.yml +0 -0
  15. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/release-drafter.yml +0 -0
  16. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/workflows/codeql.yml +0 -0
  17. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/workflows/docs.yml +0 -0
  18. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/workflows/labeler.yml +0 -0
  19. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/workflows/publish-to-pypi.yml +0 -0
  20. {babeldoc-0.1.14 → babeldoc-0.1.16}/.github/workflows/test.yml +0 -0
  21. {babeldoc-0.1.14 → babeldoc-0.1.16}/.gitignore +0 -0
  22. {babeldoc-0.1.14 → babeldoc-0.1.16}/.pre-commit-config.yaml +0 -0
  23. {babeldoc-0.1.14 → babeldoc-0.1.16}/LICENSE +0 -0
  24. {babeldoc-0.1.14 → babeldoc-0.1.16}/README.md +0 -0
  25. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/asynchronize/__init__.py +0 -0
  26. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/converter.py +0 -0
  27. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/__init__.py +0 -0
  28. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/backend/__init__.py +0 -0
  29. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/frontend/__init__.py +0 -0
  30. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/frontend/il_creater.py +0 -0
  31. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/il_version_1.py +0 -0
  32. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/il_version_1.rnc +0 -0
  33. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/il_version_1.rng +0 -0
  34. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/il_version_1.xsd +0 -0
  35. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/midend/__init__.py +0 -0
  36. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/midend/add_debug_information.py +0 -0
  37. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/midend/il_translator.py +0 -0
  38. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/midend/layout_parser.py +0 -0
  39. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/midend/paragraph_finder.py +0 -0
  40. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/midend/remove_descent.py +0 -0
  41. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/midend/styles_and_formulas.py +0 -0
  42. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/midend/typesetting.py +0 -0
  43. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/translator/__init__.py +0 -0
  44. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/translator/cache.py +0 -0
  45. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/translator/translator.py +0 -0
  46. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/utils/fontmap.py +0 -0
  47. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/utils/layout_helper.py +0 -0
  48. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/utils/style_helper.py +0 -0
  49. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/document_il/xml_converter.py +0 -0
  50. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/docvision/README.md +0 -0
  51. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/docvision/__init__.py +0 -0
  52. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/docvision/doclayout.py +0 -0
  53. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/high_level.py +0 -0
  54. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/pdfinterp.py +0 -0
  55. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/progress_monitor.py +0 -0
  56. {babeldoc-0.1.14 → babeldoc-0.1.16}/babeldoc/translation_config.py +0 -0
  57. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/CODE_OF_CONDUCT.md +0 -0
  58. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/CONTRIBUTING.md +0 -0
  59. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/CONTRIBUTOR_REWARD.md +0 -0
  60. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
  61. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
  62. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
  63. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
  64. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
  65. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/ImplementationDetails/README.md +0 -0
  66. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
  67. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
  68. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/README.md +0 -0
  69. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/deploy.sh +0 -0
  70. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/images/babeldoc-banner.png +0 -0
  71. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/images/babeldoc-contributor_reward_example.png +0 -0
  72. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/images/babeldoc-preview.gif +0 -0
  73. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/index.md +0 -0
  74. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/intro-to-pdf-object.md +0 -0
  75. {babeldoc-0.1.14 → babeldoc-0.1.16}/docs/requirements.txt +0 -0
  76. {babeldoc-0.1.14 → babeldoc-0.1.16}/mkdocs.yml +0 -0
  77. {babeldoc-0.1.14 → babeldoc-0.1.16}/tests/test_translation_config.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: BabelDOC
3
- Version: 0.1.14
3
+ Version: 0.1.16
4
4
  Summary: Yet Another Document Translator
5
5
  Project-URL: Homepage, https://github.com/funstory-ai/BabelDOC
6
6
  Project-URL: Issues, https://github.com/funstory-ai/BabelDOC/issues
@@ -26,6 +26,7 @@ Requires-Dist: peewee>=3.17.8
26
26
  Requires-Dist: pydantic>=2.10.6
27
27
  Requires-Dist: pymupdf>=1.25.1
28
28
  Requires-Dist: rich>=13.9.4
29
+ Requires-Dist: tenacity>=9.0.0
29
30
  Requires-Dist: toml>=0.10.2
30
31
  Requires-Dist: tqdm>=4.67.1
31
32
  Requires-Dist: xsdata[cli,lxml,soap]>=24.12
@@ -0,0 +1 @@
1
+ __version__ = "0.1.16"
@@ -2,7 +2,7 @@ import shutil
2
2
  import subprocess
3
3
  from pathlib import Path
4
4
 
5
- __version__ = "0.1.14"
5
+ __version__ = "0.1.16"
6
6
 
7
7
  CACHE_FOLDER = Path.home() / ".cache" / "babeldoc"
8
8
 
@@ -38,6 +38,44 @@ def _subset_fonts_process(pdf_path, output_path):
38
38
  os._exit(1)
39
39
 
40
40
 
41
+ def _save_pdf_clean_process(
42
+ pdf_path,
43
+ output_path,
44
+ garbage=1,
45
+ deflate=True,
46
+ clean=True,
47
+ deflate_fonts=True,
48
+ linear=False,
49
+ ):
50
+ """Function to run in subprocess for saving PDF with clean=True which can be time-consuming.
51
+
52
+ Args:
53
+ pdf_path: Path to the PDF file to save
54
+ output_path: Path where to save the result
55
+ garbage: Garbage collection level (0, 1, 2, 3, 4)
56
+ deflate: Whether to deflate the PDF
57
+ clean: Whether to clean the PDF
58
+ deflate_fonts: Whether to deflate fonts
59
+ linear: Whether to linearize the PDF
60
+ """
61
+ try:
62
+ pdf = pymupdf.open(pdf_path)
63
+ pdf.save(
64
+ output_path,
65
+ garbage=garbage,
66
+ deflate=deflate,
67
+ clean=clean,
68
+ deflate_fonts=deflate_fonts,
69
+ linear=linear,
70
+ )
71
+ # 返回0表示成功
72
+ os._exit(0)
73
+ except Exception as e:
74
+ logger.error(f"Error in save PDF with clean=True subprocess: {e}")
75
+ # 返回1表示失败
76
+ os._exit(1)
77
+
78
+
41
79
  class PDFCreater:
42
80
  stage_name = "Generate drawing instructions"
43
81
 
@@ -425,6 +463,11 @@ class PDFCreater:
425
463
  if process.is_alive():
426
464
  logger.warning("Subprocess did not terminate, killing it")
427
465
  process.kill()
466
+ process.terminate()
467
+ process.kill()
468
+ process.terminate()
469
+ process.kill()
470
+ process.terminate()
428
471
  except Exception as e:
429
472
  logger.error(f"Error terminating font subsetting process: {e}")
430
473
 
@@ -450,6 +493,148 @@ class PDFCreater:
450
493
  )
451
494
  return original_pdf
452
495
 
496
+ def save_pdf_with_timeout(
497
+ self,
498
+ pdf: pymupdf.Document,
499
+ output_path: str,
500
+ translation_config: TranslationConfig,
501
+ garbage: int = 1,
502
+ deflate: bool = True,
503
+ clean: bool = True,
504
+ deflate_fonts: bool = True,
505
+ linear: bool = False,
506
+ timeout: int = 120,
507
+ ) -> bool:
508
+ """Save a PDF document with a timeout for the clean=True operation.
509
+
510
+ Args:
511
+ pdf: The PDF document object
512
+ output_path: Path where to save the PDF
513
+ translation_config: Translation configuration
514
+ garbage: Garbage collection level (0, 1, 2, 3, 4)
515
+ deflate: Whether to deflate the PDF
516
+ clean: Whether to clean the PDF
517
+ deflate_fonts: Whether to deflate fonts
518
+ linear: Whether to linearize the PDF
519
+ timeout: Timeout in seconds (default: 2 minutes)
520
+
521
+ Returns:
522
+ True if saved with clean=True successfully, False if fallback to clean=False was used
523
+ """
524
+ # Create temporary file paths
525
+ temp_input = str(
526
+ translation_config.get_working_file_path(
527
+ f"temp_save_input_{int(time.time())}.pdf"
528
+ )
529
+ )
530
+ temp_output = str(
531
+ translation_config.get_working_file_path(
532
+ f"temp_save_output_{int(time.time())}.pdf"
533
+ )
534
+ )
535
+
536
+ # Save PDF to temporary file first
537
+ pdf.save(temp_input)
538
+
539
+ # Try to save with clean=True in a subprocess
540
+ process = Process(
541
+ target=_save_pdf_clean_process,
542
+ args=(
543
+ temp_input,
544
+ temp_output,
545
+ garbage,
546
+ deflate,
547
+ clean,
548
+ deflate_fonts,
549
+ linear,
550
+ ),
551
+ )
552
+ process.start()
553
+
554
+ # Wait for subprocess with timeout
555
+ start_time = time.time()
556
+
557
+ while process.is_alive():
558
+ if time.time() - start_time > timeout:
559
+ logger.warning(
560
+ f"PDF save with clean=True timeout after {timeout} seconds, terminating subprocess"
561
+ )
562
+ process.terminate()
563
+ try:
564
+ process.join(5) # Give it 5 seconds to clean up
565
+ if process.is_alive():
566
+ logger.warning("Subprocess did not terminate, killing it")
567
+ process.kill()
568
+ process.terminate()
569
+ process.kill()
570
+ process.terminate()
571
+ process.kill()
572
+ process.terminate()
573
+ except Exception as e:
574
+ logger.error(f"Error terminating PDF save process: {e}")
575
+
576
+ # Fallback to save without clean parameter
577
+ logger.info("Falling back to save without clean=True")
578
+ try:
579
+ pdf.save(
580
+ output_path,
581
+ garbage=garbage,
582
+ deflate=deflate,
583
+ clean=False,
584
+ deflate_fonts=deflate_fonts,
585
+ linear=linear,
586
+ )
587
+ return False
588
+ except Exception as e:
589
+ logger.error(f"Error in fallback save: {e}")
590
+ # Last resort: basic save
591
+ pdf.save(output_path)
592
+ return False
593
+
594
+ time.sleep(0.5) # Check every half second
595
+
596
+ # Process completed, check exit code
597
+ exit_code = process.exitcode
598
+ success = exit_code == 0
599
+
600
+ # Check if save was successful
601
+ if (
602
+ success
603
+ and Path(temp_output).exists()
604
+ and Path(temp_output).stat().st_size > 0
605
+ ):
606
+ logger.info("PDF save with clean=True completed successfully")
607
+ # Copy the successfully created file to the target path
608
+ try:
609
+ import shutil
610
+
611
+ shutil.copy2(temp_output, output_path)
612
+ return True
613
+ except Exception as e:
614
+ logger.error(f"Error copying saved PDF: {e}")
615
+ pdf.save(output_path) # Fallback to direct save
616
+ return False
617
+ else:
618
+ logger.warning(
619
+ f"PDF save with clean=True failed with exit code {exit_code} or produced empty file"
620
+ )
621
+ # Fallback to save without clean parameter
622
+ try:
623
+ pdf.save(
624
+ output_path,
625
+ garbage=garbage,
626
+ deflate=deflate,
627
+ clean=False,
628
+ deflate_fonts=deflate_fonts,
629
+ linear=linear,
630
+ )
631
+ except Exception as e:
632
+ logger.error(f"Error in fallback save: {e}")
633
+ # Last resort: basic save
634
+ pdf.save(output_path)
635
+
636
+ return False
637
+
453
638
  def write(self, translation_config: TranslationConfig) -> TranslateResult:
454
639
  basename = Path(translation_config.input_file).stem
455
640
  debug_suffix = ".debug" if translation_config.debug else ""
@@ -579,8 +764,10 @@ class PDFCreater:
579
764
  pretty=True,
580
765
  )
581
766
  translation_config.raise_if_cancelled()
582
- pdf.save(
767
+ self.save_pdf_with_timeout(
768
+ pdf,
583
769
  mono_out_path,
770
+ translation_config,
584
771
  garbage=1,
585
772
  deflate=True,
586
773
  clean=not translation_config.skip_clean,
@@ -627,8 +814,10 @@ class PDFCreater:
627
814
  exc_info=True,
628
815
  )
629
816
 
630
- dual.save(
817
+ self.save_pdf_with_timeout(
818
+ dual,
631
819
  dual_out_path,
820
+ translation_config,
632
821
  garbage=1,
633
822
  deflate=True,
634
823
  clean=not translation_config.skip_clean,
@@ -5,6 +5,10 @@ import cv2
5
5
  import httpx
6
6
  import msgpack
7
7
  import numpy as np
8
+ from tenacity import retry
9
+ from tenacity import retry_if_exception_type
10
+ from tenacity import stop_after_attempt
11
+ from tenacity import wait_exponential
8
12
 
9
13
  from babeldoc.docvision.doclayout import DocLayoutModel
10
14
  from babeldoc.docvision.doclayout import YoloBox
@@ -34,6 +38,17 @@ def encode_image(image) -> bytes:
34
38
  return encoded
35
39
 
36
40
 
41
+ @retry(
42
+ stop=stop_after_attempt(3), # 最多重试3次
43
+ wait=wait_exponential(
44
+ multiplier=1, min=1, max=10
45
+ ), # 指数退避策略,初始1秒,最大10秒
46
+ retry=retry_if_exception_type((httpx.HTTPError, Exception)), # 针对哪些异常重试
47
+ before_sleep=lambda retry_state: logger.warning(
48
+ f"Request failed, retrying in {retry_state.next_action.sleep} seconds... "
49
+ f"(Attempt {retry_state.attempt_number}/3)"
50
+ ),
51
+ )
37
52
  def predict_layout(
38
53
  image,
39
54
  host: str = "http://localhost:8000",
@@ -50,53 +65,49 @@ def predict_layout(
50
65
  Returns:
51
66
  List of predictions containing bounding boxes and classes
52
67
  """
53
- try:
54
- # Prepare request data
55
- if not isinstance(image, list):
56
- image = [image]
57
- image_data = [encode_image(image) for image in image]
58
- data = {
59
- "image": image_data,
60
- "imgsz": imgsz,
61
- }
62
-
63
- # Pack data using msgpack
64
- packed_data = msgpack.packb(data, use_bin_type=True)
65
- logger.debug(f"Packed data size: {len(packed_data)} bytes")
66
-
67
- # Send request
68
- logger.debug(f"Sending request to {host}/inference")
69
- response = httpx.post(
70
- f"{host}/inference",
71
- data=packed_data,
72
- headers={
73
- "Content-Type": "application/msgpack",
74
- "Accept": "application/msgpack",
75
- },
76
- timeout=300,
77
- follow_redirects=True,
68
+ # Prepare request data
69
+ if not isinstance(image, list):
70
+ image = [image]
71
+ image_data = [encode_image(image) for image in image]
72
+ data = {
73
+ "image": image_data,
74
+ "imgsz": imgsz,
75
+ }
76
+
77
+ # Pack data using msgpack
78
+ packed_data = msgpack.packb(data, use_bin_type=True)
79
+ logger.debug(f"Packed data size: {len(packed_data)} bytes")
80
+
81
+ # Send request
82
+ logger.debug(f"Sending request to {host}/inference")
83
+ response = httpx.post(
84
+ f"{host}/inference",
85
+ data=packed_data,
86
+ headers={
87
+ "Content-Type": "application/msgpack",
88
+ "Accept": "application/msgpack",
89
+ },
90
+ timeout=300,
91
+ follow_redirects=True,
92
+ )
93
+
94
+ logger.debug(f"Response status: {response.status_code}")
95
+ logger.debug(f"Response headers: {response.headers}")
96
+
97
+ if response.status_code == 200:
98
+ try:
99
+ result = msgpack.unpackb(response.content, raw=False)
100
+ return result
101
+ except Exception as e:
102
+ logger.exception(f"Failed to unpack response: {e!s}")
103
+ raise
104
+ else:
105
+ logger.error(f"Request failed with status {response.status_code}")
106
+ logger.error(f"Response content: {response.content}")
107
+ raise Exception(
108
+ f"Request failed with status {response.status_code}: {response.text}",
78
109
  )
79
110
 
80
- logger.debug(f"Response status: {response.status_code}")
81
- logger.debug(f"Response headers: {response.headers}")
82
-
83
- if response.status_code == 200:
84
- try:
85
- result = msgpack.unpackb(response.content, raw=False)
86
- return result
87
- except Exception as e:
88
- logger.exception(f"Failed to unpack response: {e!s}")
89
- raise
90
- else:
91
- logger.error(f"Request failed with status {response.status_code}")
92
- logger.error(f"Response content: {response.content}")
93
- raise Exception(
94
- f"Request failed with status {response.status_code}: {response.text}",
95
- )
96
- except Exception as e:
97
- logger.exception(f"Unexpected error: {e!s}")
98
- raise
99
-
100
111
 
101
112
  class RpcDocLayoutModel(DocLayoutModel):
102
113
  """DocLayoutModel implementation that uses RPC service."""
@@ -23,7 +23,7 @@ from babeldoc.docvision.rpc_doclayout import RpcDocLayoutModel
23
23
  from babeldoc.translation_config import TranslationConfig
24
24
 
25
25
  logger = logging.getLogger(__name__)
26
- __version__ = "0.1.14"
26
+ __version__ = "0.1.16"
27
27
 
28
28
 
29
29
  def create_parser():
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "BabelDOC"
3
- version = "0.1.14"
3
+ version = "0.1.16"
4
4
  description = "Yet Another Document Translator"
5
5
  license = "AGPL-3.0"
6
6
  readme = "README.md"
@@ -30,6 +30,7 @@ dependencies = [
30
30
  "xsdata[cli,lxml,soap]>=24.12",
31
31
  "msgpack>=1.1.0",
32
32
  "pydantic>=2.10.6",
33
+ "tenacity>=9.0.0",
33
34
  ]
34
35
 
35
36
  [project.urls]
@@ -131,7 +132,7 @@ pythonpath = [".", "src"]
131
132
  testpaths = ["tests"]
132
133
 
133
134
  [bumpver]
134
- current_version = "0.1.14"
135
+ current_version = "0.1.16"
135
136
  version_pattern = "MAJOR.MINOR.PATCH[.PYTAGNUM]"
136
137
 
137
138
  [bumpver.file_patterns]
@@ -147,4 +148,4 @@ version_pattern = "MAJOR.MINOR.PATCH[.PYTAGNUM]"
147
148
  ]
148
149
  "babeldoc/const.py" = [
149
150
  '__version__ = "{version}"'
150
- ]
151
+ ]
@@ -48,7 +48,7 @@ wheels = [
48
48
 
49
49
  [[package]]
50
50
  name = "babeldoc"
51
- version = "0.1.14"
51
+ version = "0.1.16"
52
52
  source = { editable = "." }
53
53
  dependencies = [
54
54
  { name = "bitstring" },
@@ -67,6 +67,7 @@ dependencies = [
67
67
  { name = "pydantic" },
68
68
  { name = "pymupdf" },
69
69
  { name = "rich" },
70
+ { name = "tenacity" },
70
71
  { name = "toml" },
71
72
  { name = "tqdm" },
72
73
  { name = "xsdata", extra = ["cli", "lxml", "soap"] },
@@ -105,6 +106,7 @@ requires-dist = [
105
106
  { name = "pydantic", specifier = ">=2.10.6" },
106
107
  { name = "pymupdf", specifier = ">=1.25.1" },
107
108
  { name = "rich", specifier = ">=13.9.4" },
109
+ { name = "tenacity", specifier = ">=9.0.0" },
108
110
  { name = "toml", specifier = ">=0.10.2" },
109
111
  { name = "tqdm", specifier = ">=4.67.1" },
110
112
  { name = "xsdata", extras = ["cli", "lxml", "soap"], specifier = ">=24.12" },
@@ -1753,6 +1755,15 @@ wheels = [
1753
1755
  { url = "https://files.pythonhosted.org/packages/99/ff/c87e0622b1dadea79d2fb0b25ade9ed98954c9033722eb707053d310d4f3/sympy-1.13.3-py3-none-any.whl", hash = "sha256:54612cf55a62755ee71824ce692986f23c88ffa77207b30c1368eda4a7060f73", size = 6189483 },
1754
1756
  ]
1755
1757
 
1758
+ [[package]]
1759
+ name = "tenacity"
1760
+ version = "9.0.0"
1761
+ source = { registry = "https://pypi.org/simple" }
1762
+ sdist = { url = "https://files.pythonhosted.org/packages/cd/94/91fccdb4b8110642462e653d5dcb27e7b674742ad68efd146367da7bdb10/tenacity-9.0.0.tar.gz", hash = "sha256:807f37ca97d62aa361264d497b0e31e92b8027044942bfa756160d908320d73b", size = 47421 }
1763
+ wheels = [
1764
+ { url = "https://files.pythonhosted.org/packages/b6/cb/b86984bed139586d01532a587464b5805f12e397594f19f931c4c2fbfa61/tenacity-9.0.0-py3-none-any.whl", hash = "sha256:93de0c98785b27fcf659856aa9f54bfbd399e29969b0621bc7f762bd441b4539", size = 28169 },
1765
+ ]
1766
+
1756
1767
  [[package]]
1757
1768
  name = "toml"
1758
1769
  version = "0.10.2"
@@ -1 +0,0 @@
1
- __version__ = "0.1.14"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes