From dbae8bce7cbfdcf48a7e98aabed15901eb6dc572 Mon Sep 17 00:00:00 2001 From: Patrick Maupin Date: Fri, 7 Apr 2017 21:05:42 -0500 Subject: [PATCH] Allow PdfWriter() to be given a filename on instantiation - This will be required for later incremental PDF generation support - It makes the API more logical - This commit showcases the change by using it in various ways in the example programs. --- examples/4up.py | 4 +-- examples/alter.py | 4 +-- examples/booklet.py | 2 +- examples/extract.py | 4 +-- examples/fancy_watermark.py | 2 +- examples/poster.py | 4 +-- examples/print_two.py | 2 +- examples/rotate.py | 4 +-- examples/subset.py | 4 +-- examples/subset_booklets.py | 2 +- examples/unspread.py | 4 +-- examples/watermark.py | 2 +- pdfrw/pdfwriter.py | 51 ++++++++++++++++++++++++++++++++++--- tests/test_examples.py | 2 +- tests/test_roundtrip.py | 7 ++--- 15 files changed, 70 insertions(+), 28 deletions(-) diff --git a/examples/4up.py b/examples/4up.py index ad2bd3b..91ac64e 100755 --- a/examples/4up.py +++ b/examples/4up.py @@ -27,7 +27,7 @@ def get4(srcpages): inpfn, = sys.argv[1:] outfn = '4up.' + os.path.basename(inpfn) pages = PdfReader(inpfn).pages -writer = PdfWriter() +writer = PdfWriter(outfn) for index in range(0, len(pages), 4): writer.addpage(get4(pages[index:index + 4])) -writer.write(outfn) +writer.write() diff --git a/examples/alter.py b/examples/alter.py index 45b9c76..bb236fa 100755 --- a/examples/alter.py +++ b/examples/alter.py @@ -19,6 +19,4 @@ trailer = PdfReader(inpfn) trailer.Info.Title = 'My New Title Goes Here' -writer = PdfWriter() -writer.trailer = trailer -writer.write(outfn) +PdfWriter(outfn, trailer=trailer).write() diff --git a/examples/booklet.py b/examples/booklet.py index f7a1621..e6b523d 100755 --- a/examples/booklet.py +++ b/examples/booklet.py @@ -53,4 +53,4 @@ def fixpage(*pages): opages += ipages -PdfWriter().addpages(opages).write(outfn) +PdfWriter(outfn).addpages(opages).write() diff --git a/examples/extract.py b/examples/extract.py index 3756b4f..dd6e267 100755 --- a/examples/extract.py +++ b/examples/extract.py @@ -22,6 +22,6 @@ pages = list(page_per_xobj(PdfReader(inpfn).pages, margin=0.5*72)) if not pages: raise IndexError("No XObjects found") -writer = PdfWriter() +writer = PdfWriter(outfn) writer.addpages(pages) -writer.write(outfn) +writer.write() diff --git a/examples/fancy_watermark.py b/examples/fancy_watermark.py index 368afb3..e9c797d 100755 --- a/examples/fancy_watermark.py +++ b/examples/fancy_watermark.py @@ -102,4 +102,4 @@ PageMerge(page).add(wmark, prepend=underneath).render() # Write out the destination file -PdfWriter().write(outfn, trailer) +PdfWriter(outfn, trailer=trailer).write() diff --git a/examples/poster.py b/examples/poster.py index 7f1c1c2..1db9378 100755 --- a/examples/poster.py +++ b/examples/poster.py @@ -37,7 +37,7 @@ def adjust(page, margin=36, scale=4.8): inpfn, = sys.argv[1:] outfn = 'poster.' + os.path.basename(inpfn) reader = PdfReader(inpfn) -writer = PdfWriter() +writer = PdfWriter(outfn) writer.addpage(adjust(reader.pages[0])) writer.trailer.Info = IndirectPdfDict(reader.Info or {}) -writer.write(outfn) +writer.write() diff --git a/examples/print_two.py b/examples/print_two.py index c54eaee..b710192 100755 --- a/examples/print_two.py +++ b/examples/print_two.py @@ -29,4 +29,4 @@ def fixpage(page, count=[0]): inpfn, = sys.argv[1:] outfn = 'print_two.' + os.path.basename(inpfn) pages = PdfReader(inpfn).pages -PdfWriter().addpages(fixpage(x) for x in pages).write(outfn) +PdfWriter(outfn).addpages(fixpage(x) for x in pages).write() diff --git a/examples/rotate.py b/examples/rotate.py index 8b10d05..0115401 100755 --- a/examples/rotate.py +++ b/examples/rotate.py @@ -36,6 +36,6 @@ pages[pagenum].Rotate = (int(pages[pagenum].inheritable.Rotate or 0) + rotate) % 360 -outdata = PdfWriter() +outdata = PdfWriter(outfn) outdata.trailer = trailer -outdata.write(outfn) +outdata.write() diff --git a/examples/subset.py b/examples/subset.py index 30a577a..e965850 100755 --- a/examples/subset.py +++ b/examples/subset.py @@ -20,10 +20,10 @@ ranges = ([int(y) for y in x.split('-')] for x in ranges) outfn = 'subset.%s' % os.path.basename(inpfn) pages = PdfReader(inpfn).pages -outdata = PdfWriter() +outdata = PdfWriter(outfn) for onerange in ranges: onerange = (onerange + onerange[-1:])[:2] for pagenum in range(onerange[0], onerange[1]+1): outdata.addpage(pages[pagenum-1]) -outdata.write(outfn) +outdata.write() diff --git a/examples/subset_booklets.py b/examples/subset_booklets.py index a8d3622..db0b9af 100755 --- a/examples/subset_booklets.py +++ b/examples/subset_booklets.py @@ -57,5 +57,5 @@ def fixpage(*pages): if len(ipages) >= 1: opages.append(fixpage(ipages.pop(), ipages.pop(0))) -PdfWriter().addpages(opages).write(OUTFN) +PdfWriter(OUTFN).addpages(opages).write() print 'It took '+ str(round(time.time()-START, 2))+' seconds to make the pdf subbooklets changes.' diff --git a/examples/unspread.py b/examples/unspread.py index 4b3bc5d..4caa973 100755 --- a/examples/unspread.py +++ b/examples/unspread.py @@ -26,7 +26,7 @@ def splitpage(src): inpfn, = sys.argv[1:] outfn = 'unspread.' + os.path.basename(inpfn) -writer = PdfWriter() +writer = PdfWriter(outfn) for page in PdfReader(inpfn).pages: writer.addpages(splitpage(page)) -writer.write(outfn) +writer.write() diff --git a/examples/watermark.py b/examples/watermark.py index 799a2b2..1188502 100755 --- a/examples/watermark.py +++ b/examples/watermark.py @@ -34,4 +34,4 @@ trailer = PdfReader(inpfn) for page in trailer.pages: PageMerge(page).add(wmark, prepend=underneath).render() -PdfWriter().write(outfn, trailer) +PdfWriter(outfn, trailer=trailer).write() diff --git a/pdfrw/pdfwriter.py b/pdfrw/pdfwriter.py index cf2ea6d..a7d4af4 100755 --- a/pdfrw/pdfwriter.py +++ b/pdfrw/pdfwriter.py @@ -225,11 +225,44 @@ class PdfWriter(object): _trailer = None canonicalize = False + fname = None + + def __init__(self, fname=None, version='1.3', compress=False, **kwargs): + """ + Parameters: + fname -- Output file name, or file-like binary object + with a write method + version -- PDF version to target. Currently only 1.3 + supported. + compress -- True to do compression on output. Currently + compresses stream objects. + """ + + # Legacy support: fname is new, was added in front + if fname is not None: + try: + float(fname) + except (ValueError, TypeError): + pass + else: + if version != '1.3': + assert compress == False + compress = version + version = fname + fname = None + + self.fname = fname + self.version = version + self.compress = compress + + if kwargs: + for name, value in iteritems(kwargs): + if name not in self.replaceable: + raise ValueError("Cannot set attribute %s " + "on PdfWriter instance" % name) + setattr(self, name, value) - def __init__(self, version='1.3', compress=False): self.pagearray = PdfArray() - self.compress = compress - self.version = version self.killobj = {} def addpage(self, page): @@ -301,10 +334,18 @@ def _set_trailer(self, trailer): trailer = property(_get_trailer, _set_trailer) - def write(self, fname, trailer=None, user_fmt=user_fmt, + def write(self, fname=None, trailer=None, user_fmt=user_fmt, disable_gc=True): + trailer = trailer or self.trailer + # Support fname for legacy applications + if (fname is not None) == (self.fname is not None): + raise PdfOutputError( + "PdfWriter fname must be specified exactly once") + + fname = fname or self.fname + # Dump the data. We either have a filename or a preexisting # file object. preexisting = hasattr(fname, 'write') @@ -340,3 +381,5 @@ def make_canonical(self): workitems += obj else: workitems += obj.values() + + replaceable = set(vars()) \ No newline at end of file diff --git a/tests/test_examples.py b/tests/test_examples.py index baa98a6..6871b80 100755 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -96,7 +96,7 @@ def do_test(self, params, prev_results=[''], scrub=False): os.remove(scrub) subprocess.call(params) if scrub: - PdfWriter().addpages(PdfReader(scrub).pages).write(dstf) + PdfWriter(dstf).addpages(PdfReader(scrub).pages).write() with open(dstf, 'rb') as f: data = f.read() size = len(data) diff --git a/tests/test_roundtrip.py b/tests/test_roundtrip.py index b6f8b2e..a8349a6 100755 --- a/tests/test_roundtrip.py +++ b/tests/test_roundtrip.py @@ -79,11 +79,12 @@ def roundtrip(self, testname, basename, srcf, decompress=False, result = 'skip -- encrypt' hash = '------skip-encrypt-no-file------' return self.skipTest('File encrypted') - writer = pdfrw.PdfWriter(compress=compress) + writer = pdfrw.PdfWriter(dstf, compress=compress) if repaginate: writer.addpages(trailer.pages) - trailer = None - writer.write(dstf, trailer) + else: + writer.trailer = trailer + writer.write() with open(dstf, 'rb') as f: data = f.read() size = len(data)