From bfa3c202c5b422b27b6ffc074697f6e64a53b6b3 Mon Sep 17 00:00:00 2001 From: Johannes 'josch' Schauer Date: Tue, 28 Apr 2020 13:41:41 +0200 Subject: New upstream version 0.3.5 --- src/img2pdf.egg-info/PKG-INFO | 6 +- src/img2pdf.py | 181 +++++++++++++++--------------------------- src/tests/__init__.py | 42 ++++------ 3 files changed, 79 insertions(+), 150 deletions(-) (limited to 'src') diff --git a/src/img2pdf.egg-info/PKG-INFO b/src/img2pdf.egg-info/PKG-INFO index 9919a51..8fa2d93 100644 --- a/src/img2pdf.egg-info/PKG-INFO +++ b/src/img2pdf.egg-info/PKG-INFO @@ -1,12 +1,12 @@ Metadata-Version: 2.1 Name: img2pdf -Version: 0.3.4 +Version: 0.3.5 Summary: Convert images to PDF via direct JPEG inclusion. Home-page: https://gitlab.mister-muffin.de/josch/img2pdf Author: Johannes 'josch' Schauer Author-email: josch@mister-muffin.de License: LGPL -Download-URL: https://gitlab.mister-muffin.de/josch/img2pdf/repository/archive.tar.gz?ref=0.3.4 +Download-URL: https://gitlab.mister-muffin.de/josch/img2pdf/repository/archive.tar.gz?ref=0.3.5 Description: [![Travis Status](https://travis-ci.org/josch/img2pdf.svg?branch=master)](https://travis-ci.org/josch/img2pdf) [![Appveyor Status](https://ci.appveyor.com/api/projects/status/2kws3wkqvi526llj/branch/master?svg=true)](https://ci.appveyor.com/project/josch/img2pdf/branch/master) @@ -303,8 +303,6 @@ Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Other Audience Classifier: Environment :: Console Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: Implementation :: CPython diff --git a/src/img2pdf.py b/src/img2pdf.py index 764e745..ef438b5 100755 --- a/src/img2pdf.py +++ b/src/img2pdf.py @@ -34,9 +34,15 @@ import logging import struct import platform -PY3 = sys.version_info[0] >= 3 +with_pdfrw = False +try: + import pdfrw -__version__ = "0.3.4" + with_pdfrw = True +except ImportError: + pass + +__version__ = "0.3.5" default_dpi = 96.0 papersizes = { "letter": "8.5inx11in", @@ -566,49 +572,26 @@ class MyPdfWriter: self.addobj(page) -if PY3: - - class MyPdfString: - @classmethod - def encode(cls, string, hextype=False): - if hextype: - return ( - b"< " - + b" ".join(("%06x" % c).encode("ascii") for c in string) - + b" >" - ) - else: - try: - string = string.encode("ascii") - except UnicodeEncodeError: - string = b"\xfe\xff" + string.encode("utf-16-be") - # We should probably encode more here because at least - # ghostscript interpretes a carriage return byte (0x0D) as a - # new line byte (0x0A) - # PDF supports: \n, \r, \t, \b and \f - string = string.replace(b"\\", b"\\\\") - string = string.replace(b"(", b"\\(") - string = string.replace(b")", b"\\)") - return b"(" + string + b")" - - -else: - - class MyPdfString(object): - @classmethod - def encode(cls, string, hextype=False): - if hextype: - return ( - b"< " - + b" ".join(("%06x" % c).encode("ascii") for c in string) - + b" >" - ) - else: - # This mimics exactely to what pdfrw does. - string = string.replace(b"\\", b"\\\\") - string = string.replace(b"(", b"\\(") - string = string.replace(b")", b"\\)") - return b"(" + string + b")" +class MyPdfString: + @classmethod + def encode(cls, string, hextype=False): + if hextype: + return ( + b"< " + b" ".join(("%06x" % c).encode("ascii") for c in string) + b" >" + ) + else: + try: + string = string.encode("ascii") + except UnicodeEncodeError: + string = b"\xfe\xff" + string.encode("utf-16-be") + # We should probably encode more here because at least + # ghostscript interpretes a carriage return byte (0x0D) as a + # new line byte (0x0A) + # PDF supports: \n, \r, \t, \b and \f + string = string.replace(b"\\", b"\\\\") + string = string.replace(b"(", b"\\(") + string = string.replace(b")", b"\\)") + return b"(" + string + b")" class pdfdoc(object): @@ -631,25 +614,14 @@ class pdfdoc(object): fit_window=False, center_window=False, fullscreen=False, - with_pdfrw=True, ): if with_pdfrw: - try: - from pdfrw import PdfWriter, PdfDict, PdfName, PdfString - - self.with_pdfrw = True - except ImportError: - PdfWriter = MyPdfWriter - PdfDict = MyPdfDict - PdfName = MyPdfName - PdfString = MyPdfString - self.with_pdfrw = False + from pdfrw import PdfWriter, PdfDict, PdfName, PdfString else: PdfWriter = MyPdfWriter PdfDict = MyPdfDict PdfName = MyPdfName PdfString = MyPdfString - self.with_pdfrw = False now = datetime.now() self.info = PdfDict(indirect=True) @@ -690,7 +662,7 @@ class pdfdoc(object): self.writer.version = version # this is done because pdfrw adds info, catalog and pages as the first # three objects in this order - if not self.with_pdfrw: + if not with_pdfrw: self.writer.addobj(self.info) self.writer.addobj(self.writer.catalog) self.writer.addobj(self.writer.pages) @@ -726,7 +698,7 @@ class pdfdoc(object): trimborder=None, artborder=None, ): - if self.with_pdfrw: + if with_pdfrw: from pdfrw import PdfDict, PdfName, PdfObject, PdfString from pdfrw.py23_diffs import convert_load else: @@ -743,7 +715,7 @@ class pdfdoc(object): elif color == Colorspace.CMYK or color == Colorspace["CMYK;I"]: colorspace = PdfName.DeviceCMYK elif color == Colorspace.P: - if self.with_pdfrw: + if with_pdfrw: raise Exception( "pdfrw does not support hex strings for " "palette image input, re-run with " @@ -871,7 +843,7 @@ class pdfdoc(object): self.writer.addpage(page) - if not self.with_pdfrw: + if not with_pdfrw: self.writer.addobj(content) self.writer.addobj(image) @@ -881,7 +853,7 @@ class pdfdoc(object): return stream.getvalue() def tostream(self, outputstream): - if self.with_pdfrw: + if with_pdfrw: from pdfrw import PdfDict, PdfName, PdfArray, PdfObject else: PdfDict = MyPdfDict @@ -899,7 +871,7 @@ class pdfdoc(object): # is added, so we can only start using it after all pages have been # written. - if self.with_pdfrw: + if with_pdfrw: catalog = self.writer.trailer.Root else: catalog = self.writer.catalog @@ -1005,7 +977,7 @@ class pdfdoc(object): raise ValueError("unknown page layout: %s" % self.page_layout) # now write out the PDF - if self.with_pdfrw: + if with_pdfrw: self.writer.trailer.Info = self.info self.writer.write(outputstream) else: @@ -1809,7 +1781,6 @@ def convert(*images, **kwargs): viewer_fit_window=False, viewer_center_window=False, viewer_fullscreen=False, - with_pdfrw=True, outputstream=None, first_frame_only=False, allow_oversized=True, @@ -1821,6 +1792,9 @@ def convert(*images, **kwargs): for kwname, default in _default_kwargs.items(): if kwname not in kwargs: kwargs[kwname] = default + if "with_pdfrw" in kwargs: + global with_pdfrw + with_pdfrw = kwargs["with_pdfrw"] pdf = pdfdoc( "1.3", @@ -1840,7 +1814,6 @@ def convert(*images, **kwargs): kwargs["viewer_fit_window"], kwargs["viewer_center_window"], kwargs["viewer_fullscreen"], - kwargs["with_pdfrw"], ) # backwards compatibility with older img2pdf versions where the first @@ -2111,39 +2084,23 @@ def parse_borderarg(string): def input_images(path): if path == "-": # we slurp in all data from stdin because we need to seek in it later - if PY3: - result = sys.stdin.buffer.read() - else: - result = sys.stdin.read() + result = sys.stdin.buffer.read() if len(result) == 0: raise argparse.ArgumentTypeError('"%s" is empty' % path) else: - if PY3: - try: - if os.path.getsize(path) == 0: - raise argparse.ArgumentTypeError('"%s" is empty' % path) - # test-read a byte from it so that we can abort early in case - # we cannot read data from the file - with open(path, "rb") as im: - im.read(1) - except IsADirectoryError: - raise argparse.ArgumentTypeError('"%s" is a directory' % path) - except PermissionError: - raise argparse.ArgumentTypeError('"%s" permission denied' % path) - except FileNotFoundError: - raise argparse.ArgumentTypeError('"%s" does not exist' % path) - else: - try: - if os.path.getsize(path) == 0: - raise argparse.ArgumentTypeError('"%s" is empty' % path) - # test-read a byte from it so that we can abort early in case - # we cannot read data from the file - with open(path, "rb") as im: - im.read(1) - except IOError as err: - raise argparse.ArgumentTypeError(str(err)) - except OSError as err: - raise argparse.ArgumentTypeError(str(err)) + try: + if os.path.getsize(path) == 0: + raise argparse.ArgumentTypeError('"%s" is empty' % path) + # test-read a byte from it so that we can abort early in case + # we cannot read data from the file + with open(path, "rb") as im: + im.read(1) + except IsADirectoryError: + raise argparse.ArgumentTypeError('"%s" is a directory' % path) + except PermissionError: + raise argparse.ArgumentTypeError('"%s" permission denied' % path) + except FileNotFoundError: + raise argparse.ArgumentTypeError('"%s" does not exist' % path) result = path return result @@ -2492,6 +2449,9 @@ def gui(): v for v in Colorspace if v.name == args["colorspace"].get() ) + global with_pdfrw + if with_pdfrw: + with_pdfrw = not args["without_pdfrw"].get() convert( *infiles, title=args["title"].get() if args["title"].get() else None, @@ -2516,7 +2476,6 @@ def gui(): viewer_fit_window=(args["viewer_fit_window"].get() or None), viewer_center_window=(args["viewer_center_window"].get() or None), viewer_fullscreen=(args["viewer_fullscreen"].get() or None), - with_pdfrw=not args["without_pdfrw"].get(), outputstream=stream, first_frame_only=args["first_frame_only"].get(), cropborder=None, @@ -2631,6 +2590,7 @@ def gui(): variable=args["nodate"], state=tkinter.DISABLED, ).grid(row=1, column=0, columnspan=2, sticky=tkinter.W) + # TODO: only have this checkbox enabled if pdfrw is installed tkinter.Checkbutton( output_options, text="without pdfrw", @@ -3085,23 +3045,9 @@ Report bugs at https://gitlab.mister-muffin.de/josch/img2pdf/issues version="%(prog)s " + __version__, help="Prints version information and exits.", ) - gui_group = parser.add_mutually_exclusive_group(required=False) - gui_group.add_argument( - "--gui", - dest="gui", - action="store_true", - help="run tkinter gui (default on Windows)", - ) - gui_group.add_argument( - "--nogui", - dest="gui", - action="store_false", - help="don't run tkinter gui (default elsewhere)", + parser.add_argument( + "--gui", dest="gui", action="store_true", help="run experimental tkinter gui" ) - if platform.system() == "Windows": - parser.set_defaults(gui=True) - else: - parser.set_defaults(gui=False) outargs = parser.add_argument_group( title="General output arguments", @@ -3465,10 +3411,7 @@ and left/right, respectively. It is not possible to specify asymmetric borders. if len(args.images) == 0: logging.info("reading image from standard input") try: - if PY3: - args.images = [sys.stdin.buffer.read()] - else: - args.images = [sys.stdin.read()] + args.images = [sys.stdin.buffer.read()] except KeyboardInterrupt: exit(0) @@ -3490,6 +3433,9 @@ and left/right, respectively. It is not possible to specify asymmetric borders. ) exit(2) + global with_pdfrw + if with_pdfrw: + with_pdfrw = not args.without_pdfrw try: convert( *args.images, @@ -3511,7 +3457,6 @@ and left/right, respectively. It is not possible to specify asymmetric borders. viewer_fit_window=args.viewer_fit_window, viewer_center_window=args.viewer_center_window, viewer_fullscreen=args.viewer_fullscreen, - with_pdfrw=not args.without_pdfrw, outputstream=args.output, first_frame_only=args.first_frame_only, cropborder=args.crop_border, diff --git a/src/tests/__init__.py b/src/tests/__init__.py index 807aa84..7997218 100644 --- a/src/tests/__init__.py +++ b/src/tests/__init__.py @@ -10,12 +10,7 @@ from io import StringIO, BytesIO, TextIOWrapper HERE = os.path.dirname(__file__) -PY3 = sys.version_info[0] >= 3 - -if PY3: - PdfReaderIO = StringIO -else: - PdfReaderIO = BytesIO +PdfReaderIO = StringIO # Recompressing the image stream makes the comparison robust against output # preserving changes in the zlib compress output bitstream @@ -480,29 +475,15 @@ def tiff_header_for_ccitt(width, height, img_size, ccitt_group=4): class CommandLineTests(unittest.TestCase): def test_main_help(self): - if PY3: - from contextlib import redirect_stdout - f = StringIO() - with redirect_stdout(f): - try: - img2pdf.main(['img2pdf', '--help']) - except SystemExit: - pass - res = f.getvalue() - self.assertIn('img2pdf', res) - else: - # silence output - sys_stdout = sys.stdout - sys.stdout = BytesIO() - + from contextlib import redirect_stdout + f = StringIO() + with redirect_stdout(f): try: img2pdf.main(['img2pdf', '--help']) except SystemExit: - # argparse does sys.exit(0) on --help - res = sys.stdout.getvalue() - self.assertIn('img2pdf', res) - finally: - sys.stdout = sys_stdout + pass + res = f.getvalue() + self.assertIn('img2pdf', res) def test_suite(): @@ -554,12 +535,17 @@ def test_suite(): assert os.path.isfile(outputf) def handle(self, f=inputf, out=outputf, with_pdfrw=with_pdfrw): + try: + from pdfrw import PdfReader, PdfName, PdfWriter + from pdfrw.py23_diffs import convert_load, convert_store + except ImportError: + # the test requires pdfrw + self.skipTest("this test requires pdfrw") + return with open(f, "rb") as inf: orig_imgdata = inf.read() output = img2pdf.convert(orig_imgdata, nodate=True, with_pdfrw=with_pdfrw) - from pdfrw import PdfReader, PdfName, PdfWriter - from pdfrw.py23_diffs import convert_load, convert_store x = PdfReader(PdfReaderIO(convert_load(output))) self.assertEqual(sorted(x.keys()), [PdfName.Info, PdfName.Root, PdfName.Size]) -- cgit v1.2.3