Fix issue #275: doesn't work when installed in non-Unicode path
Closes #275
This commit is contained in:
+31
-10
@@ -17,14 +17,18 @@
|
||||
|
||||
# Generate a PDFA_def.ps file for Ghostscript >= 9.14
|
||||
|
||||
from string import Template
|
||||
from binascii import hexlify
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from shutil import copyfile
|
||||
from string import Template
|
||||
import pkg_resources
|
||||
import os
|
||||
|
||||
from libxmp.utils import file_to_dict
|
||||
from libxmp import consts
|
||||
from pathlib import Path
|
||||
|
||||
from ocrmypdf.helpers import fspath
|
||||
|
||||
ICC_PROFILE_RELPATH = 'data/sRGB.icc'
|
||||
|
||||
@@ -36,12 +40,8 @@ SRGB_ICC_PROFILE = pkg_resources.resource_filename(
|
||||
# files, from the Ghostscript documentation. Lines beginning with % are
|
||||
# comments. Python substitution variables have a '$' prefix.
|
||||
pdfa_def_template = u"""%!
|
||||
% This is derived from Ghostscript's template for creating a PDF/A document.
|
||||
% This is a small PostScript program that includes some necessary information
|
||||
% to create a PDF/A compliant file.
|
||||
|
||||
% Define entries in the document Info dictionary :
|
||||
/ICCProfile ($icc_profile)
|
||||
/ICCProfile $icc_profile
|
||||
def
|
||||
|
||||
[$docinfo
|
||||
@@ -179,9 +179,19 @@ def _get_pdfmark_dates(pdfmark):
|
||||
|
||||
|
||||
def _get_pdfa_def(icc_profile, icc_identifier, pdfmark):
|
||||
"""Create a Postscript file for Ghostscript. pdfmark contains the various
|
||||
objects as strings; these must be encoded in ASCII, and dates have a
|
||||
special format."""
|
||||
"""
|
||||
Create a Postscript pdfmark file for Ghostscript.
|
||||
|
||||
pdfmark contains the various objects as strings; these must be encoded in
|
||||
ASCII, and dates have a special format.
|
||||
|
||||
:param icc_profile: filename of the ICC profile to include in pdfmark
|
||||
:param icc_identifier: ICC identifier such as 'sRGB'
|
||||
:param pdfmark: a dictionary containing keys to include the pdfmark
|
||||
|
||||
:returns: a string containing the entire pdfmark
|
||||
|
||||
"""
|
||||
|
||||
# Ghostscript <= 9.21 has a bug where null entries in DOCINFO might produce
|
||||
# ERROR: VMerror (-25) on closing pdfwrite device.
|
||||
@@ -212,6 +222,17 @@ def generate_pdfa_ps(target_filename, pdfmark, icc='sRGB'):
|
||||
else:
|
||||
raise NotImplementedError("Only supporting sRGB")
|
||||
|
||||
# pdfmark must contain the full path to the ICC profile, and pdfmark must
|
||||
# also encoded in ASCII. ocrmypdf can be installed anywhere, including to
|
||||
# paths that have a non-ASCII character in the filename. Ghostscript
|
||||
# accepts hex-encoded strings and converts them to byte strings, so
|
||||
# we encode the path with fsencode() and use the hex representation.
|
||||
# UTF-16 not accepted here. (Even though ASCII encodable is the usual case,
|
||||
# do this always to avoid making it a rare conditional.)
|
||||
bytes_icc_profile = os.fsencode(icc_profile)
|
||||
hex_icc_profile = hexlify(bytes_icc_profile)
|
||||
icc_profile = '<' + hex_icc_profile.decode('ascii') + '>'
|
||||
|
||||
ps = _get_pdfa_def(icc_profile, icc, pdfmark)
|
||||
|
||||
# We should have encoded everything to pure ASCII by this point, and
|
||||
|
||||
+24
-3
@@ -18,11 +18,19 @@
|
||||
|
||||
import pytest
|
||||
import PyPDF2 as pypdf
|
||||
import datetime
|
||||
from datetime import timezone
|
||||
|
||||
from ocrmypdf.pdfa import file_claims_pdfa, encode_pdf_date, decode_pdf_date
|
||||
from datetime import timezone
|
||||
from pathlib import Path
|
||||
from shutil import copyfile
|
||||
from unittest.mock import patch
|
||||
import datetime
|
||||
|
||||
from ocrmypdf.exceptions import ExitCode
|
||||
from ocrmypdf.helpers import fspath
|
||||
from ocrmypdf.pdfa import (
|
||||
file_claims_pdfa, encode_pdf_date, decode_pdf_date, generate_pdfa_ps,
|
||||
SRGB_ICC_PROFILE
|
||||
)
|
||||
|
||||
try:
|
||||
import fitz
|
||||
@@ -239,3 +247,16 @@ def test_xml_metadata_preserved(spoof_tesseract_noop, output_type,
|
||||
if propidx in before:
|
||||
assert after.get(propidx) == before[propidx] \
|
||||
or after.get(prop) == before[propidx]
|
||||
|
||||
|
||||
def test_srgb_in_unicode_path(tmpdir):
|
||||
"""Test that we can produce pdfmark when install path is not ASCII"""
|
||||
|
||||
dstdir = Path(tmpdir) / b'\xe4\x80\x80'.decode('utf-8')
|
||||
dstdir.mkdir()
|
||||
dst = dstdir / 'sRGB.icc'
|
||||
|
||||
copyfile(SRGB_ICC_PROFILE, fspath(dst))
|
||||
|
||||
with patch('ocrmypdf.pdfa.SRGB_ICC_PROFILE', new=str(dst)):
|
||||
generate_pdfa_ps(dstdir / 'out.ps', {})
|
||||
|
||||
Reference in New Issue
Block a user