BabelDOC 0.1.15__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.
- {babeldoc-0.1.15 → babeldoc-0.1.16}/PKG-INFO +1 -1
- babeldoc-0.1.16/babeldoc/__init__.py +1 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/const.py +1 -1
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/backend/pdf_creater.py +191 -2
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/main.py +1 -1
- {babeldoc-0.1.15 → babeldoc-0.1.16}/pyproject.toml +2 -2
- {babeldoc-0.1.15 → babeldoc-0.1.16}/uv.lock +1 -1
- babeldoc-0.1.15/babeldoc/__init__.py +0 -1
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.cursorignore +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/dependabot.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/labels.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/release-drafter.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/workflows/codeql.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/workflows/docs.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/workflows/labeler.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/workflows/publish-to-pypi.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.github/workflows/test.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.gitignore +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/.pre-commit-config.yaml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/LICENSE +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/README.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/asynchronize/__init__.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/converter.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/__init__.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/backend/__init__.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/frontend/__init__.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/frontend/il_creater.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/il_version_1.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/il_version_1.rnc +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/il_version_1.rng +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/il_version_1.xsd +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/midend/__init__.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/midend/add_debug_information.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/midend/il_translator.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/midend/layout_parser.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/midend/paragraph_finder.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/midend/remove_descent.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/midend/styles_and_formulas.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/midend/typesetting.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/translator/__init__.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/translator/cache.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/translator/translator.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/utils/fontmap.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/utils/layout_helper.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/utils/style_helper.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/document_il/xml_converter.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/docvision/README.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/docvision/__init__.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/docvision/doclayout.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/docvision/rpc_doclayout.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/high_level.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/pdfinterp.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/progress_monitor.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/babeldoc/translation_config.py +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/CODE_OF_CONDUCT.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/CONTRIBUTING.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/CONTRIBUTOR_REWARD.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/ILTranslator/ILTranslator.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/PDFCreation/PDFCreation.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/PDFParsing/PDFParsing.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/README.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/StylesAndFormulas/StylesAndFormulas.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/Typesetting/Typesetting.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/README.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/deploy.sh +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/images/babeldoc-banner.png +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/images/babeldoc-contributor_reward_example.png +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/images/babeldoc-preview.gif +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/index.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/intro-to-pdf-object.md +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/docs/requirements.txt +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/mkdocs.yml +0 -0
- {babeldoc-0.1.15 → babeldoc-0.1.16}/tests/test_translation_config.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.16"
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "BabelDOC"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.16"
|
|
4
4
|
description = "Yet Another Document Translator"
|
|
5
5
|
license = "AGPL-3.0"
|
|
6
6
|
readme = "README.md"
|
|
@@ -132,7 +132,7 @@ pythonpath = [".", "src"]
|
|
|
132
132
|
testpaths = ["tests"]
|
|
133
133
|
|
|
134
134
|
[bumpver]
|
|
135
|
-
current_version = "0.1.
|
|
135
|
+
current_version = "0.1.16"
|
|
136
136
|
version_pattern = "MAJOR.MINOR.PATCH[.PYTAGNUM]"
|
|
137
137
|
|
|
138
138
|
[bumpver.file_patterns]
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.15"
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/AsyncTranslate/AsyncTranslate.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{babeldoc-0.1.15 → babeldoc-0.1.16}/docs/ImplementationDetails/ParagraphFinding/ParagraphFinding.md
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|