Hello community,

here is the log from the commit of package python-PyPDF2 for openSUSE:Factory 
checked in at 2017-04-24 09:49:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-PyPDF2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-PyPDF2.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-PyPDF2"

Mon Apr 24 09:49:40 2017 rev:4 rq:489795 version:1.26.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-PyPDF2/python-PyPDF2.changes      
2015-05-16 19:01:48.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.python-PyPDF2.new/python-PyPDF2.changes 
2017-04-24 09:49:42.136162938 +0200
@@ -1,0 +2,57 @@
+Thu Apr 20 04:22:33 UTC 2017 - [email protected]
+
+- Convert to single spec
+- Update to version 1.26.0
+  * NOTE: Active maintenance on PyPDF2 is resuming after a hiatus
+  * Fixed a bug where image resources where incorrectly overwritten
+    when merging pages
+  * Added dictionary for JavaScript actions to the root (louib)
+  * Added unit tests for the JS functionality (louib)
+  * Add more Python 3 compatibility when reading inline images (im2703
+    and (VyacheslavHashov)
+  * Return NullObject instead of raising error when failing to resolve
+    object (ctate)
+  * Don't output warning for non-zeroed xref table when strict=False
+    (BenRussert)
+  * Remove extraneous zeroes from output formatting (speedplane)
+  * Fix bug where reading an inline image would cut off prematurely in
+    certain cases (speedplane)
+- Changes for 1.25
+BUGFIXES:
+    * Added Python 3 algorithm for ASCII85Decode. Fixes issue when
+      reading reportlab-generated files with Py 3 (jerickbixly)
+    * Recognize more escape sequence which would otherwise throw an
+      exception (manuelzs, robertsoakes)
+    * Fixed overflow error in generic.py. Occurred
+      when reading a too-large int in Python 2 (by Raja Jamwal)
+    * Allow access to files which were encrypted with an empty
+      password. Previously threw a "File has not been decrypted"
+      exception (Elena Williams)
+    * Do not attempt to decode an empty data stream. Previously
+      would cause an error in decode algorithms (vladir)
+    * Fixed some type issues specific to Py 2 or Py 3
+    * Fix issue when stream data begins with whitespace (soloma83)
+    * Recognize abbreviated filter names (AlmightyOatmeal and
+      Matthew Weiss)
+    * Copy decryption key from PdfFileReader to PdfFileMerger.
+      Allows usage of PdfFileMerger with encrypted files (twolfson)
+    * Fixed bug which occurred when a NameObject is present at end
+      of a file stream. Threw a "Stream has ended unexpectedly"
+      exception (speedplane)
+FEATURES:
+    * Initial work on a test suite; to be expanded in future.
+      Tests and Resources directory added, README updated (robertsoakes)
+    * Added document cloning methods to PdfFileWriter:
+      appendPagesFromReader, cloneReaderDocumentRoot, and
+      cloneDocumentFromReader. See official documentation (robertsoakes)
+    * Added method for writing to form fields: updatePageFormFieldValues.
+      This will be enhanced in the future. See official documentation
+      (robertsoakes)
+    * New addAttachment method. See documentation. Support for adding
+      and extracting embedded files to be enhanced in the future
+      (moshekaplan)
+    * Added methods to get page number of given PageObject or
+      Destination: getPageNumber and getDestinationPageNumber.
+      See documentation (mozbugbox)
+    
+-------------------------------------------------------------------

Old:
----
  PyPDF2-1.24.tar.gz

New:
----
  PyPDF2-1.26.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-PyPDF2.spec ++++++
--- /var/tmp/diff_new_pack.FuoijM/_old  2017-04-24 09:49:43.224009080 +0200
+++ /var/tmp/diff_new_pack.FuoijM/_new  2017-04-24 09:49:43.228008514 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-PyPDF2
 #
-# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,22 +16,23 @@
 #
 
 
+%{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-PyPDF2
-Version:        1.24
+Version:        1.26.0
 Release:        0
 Url:            http://mstamy2.github.com/PyPDF2
 Summary:        PDF toolkit
 License:        BSD-3-Clause
 Group:          Development/Languages/Python
-Source:         
https://pypi.python.org/packages/source/P/PyPDF2/PyPDF2-%{version}.tar.gz
+Source:         
https://pypi.io/packages/source/P/PyPDF2/PyPDF2-%{version}.tar.gz
+BuildRequires:  %{python_module devel}
+BuildRequires:  %{python_module setuptools}
+BuildRequires:  fdupes
+BuildRequires:  python-rpm-macros
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-BuildRequires:  python-devel
-BuildRequires:  python-setuptools
-%if 0%{?suse_version} && 0%{?suse_version} <= 1110
-%{!?python_sitelib: %global python_sitelib %(python -c "from 
distutils.sysconfig import get_python_lib; print get_python_lib()")}
-%else
 BuildArch:      noarch
-%endif
+
+%python_subpackages
 
 %description
 A Pure-Python library built as a PDF toolkit.  It is capable of:
@@ -54,15 +55,16 @@
 sed -i '/^#!/ d' PyPDF2/pagerange.py
 
 %build
-python setup.py build
+%python_build
 
 %install
-python setup.py install --prefix=%{_prefix} --root=%{buildroot}
+%python_install
+%fdupes %{buildroot}%{_prefix}
 chmod a-x CHANGELOG LICENSE README.md
 
-%files
+%files %{python_files}
 %defattr(-,root,root,-)
 %doc CHANGELOG LICENSE README.md
-%{python_sitelib}
+%{python_sitelib}/*
 
 %changelog

++++++ PyPDF2-1.24.tar.gz -> PyPDF2-1.26.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/.gitignore new/PyPDF2-1.26.0/.gitignore
--- old/PyPDF2-1.24/.gitignore  2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/.gitignore        2016-05-18 18:47:24.000000000 +0200
@@ -1,3 +1,6 @@
 *.pyc
 *.swp
 .DS_Store
+build
+.idea/*
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/CHANGELOG new/PyPDF2-1.26.0/CHANGELOG
--- old/PyPDF2-1.24/CHANGELOG   2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/CHANGELOG 2016-05-18 18:47:24.000000000 +0200
@@ -1,4 +1,108 @@
-Version 1.24, 2014-12-31
+Version 1.26.0, 2016-05-18
+--------------------------
+
+ - NOTE: Active maintenance on PyPDF2 is resuming after a hiatus
+
+ - Fixed a bug where image resources where incorrectly
+   overwritten when merging pages
+
+ - Added dictionary for JavaScript actions to the root (louib)
+
+ - Added unit tests for the JS functionality (louib)
+
+ - Add more Python 3 compatibility when reading inline images (im2703
+   and (VyacheslavHashov)
+
+ - Return NullObject instead of raising error when failing to resolve
+   object (ctate)
+
+ - Don't output warning for non-zeroed xref table when strict=False
+   (BenRussert)
+
+ - Remove extraneous zeroes from output formatting (speedplane)
+
+ - Fix bug where reading an inline image would cut off prematurely
+   in certain cases (speedplane)
+
+
+Patch 1.25.1, 2015-07-20
+
+ - Fix bug when parsing inline images. Occurred when merging
+   certain pages with inline images
+
+ - Fixed type error when creating outlines by utilizing the
+   isString() test
+
+Version 1.25, 2015-07-07
+------------------------
+
+BUGFIXES:
+
+ - Added Python 3 algorithm for ASCII85Decode. Fixes issue when
+   reading reportlab-generated files with Py 3 (jerickbixly)
+
+ - Recognize more escape sequence which would otherwise throw an
+   exception (manuelzs, robertsoakes)
+
+ - Fixed overflow error in generic.py. Occurred
+   when reading a too-large int in Python 2 (by Raja Jamwal)
+
+ - Allow access to files which were encrypted with an empty
+   password. Previously threw a "File has not been decrypted"
+   exception (Elena Williams)
+
+ - Do not attempt to decode an empty data stream. Previously
+   would cause an error in decode algorithms (vladir)
+
+ - Fixed some type issues specific to Py 2 or Py 3
+
+ - Fix issue when stream data begins with whitespace (soloma83)
+
+ - Recognize abbreviated filter names (AlmightyOatmeal and
+   Matthew Weiss)
+
+ - Copy decryption key from PdfFileReader to PdfFileMerger.
+   Allows usage of PdfFileMerger with encrypted files (twolfson)
+
+ - Fixed bug which occurred when a NameObject is present at end
+   of a file stream. Threw a "Stream has ended unexpectedly"
+   exception (speedplane)
+
+FEATURES:
+
+ - Initial work on a test suite; to be expanded in future.
+   Tests and Resources directory added, README updated (robertsoakes)
+
+ - Added document cloning methods to PdfFileWriter:
+   appendPagesFromReader, cloneReaderDocumentRoot, and
+   cloneDocumentFromReader. See official documentation (robertsoakes)
+
+ - Added method for writing to form fields: updatePageFormFieldValues.
+   This will be enhanced in the future. See official documentation
+   (robertsoakes)
+
+ - New addAttachment method. See documentation. Support for adding
+   and extracting embedded files to be enhanced in the future
+   (moshekaplan)
+
+ - Added methods to get page number of given PageObject or
+   Destination: getPageNumber and getDestinationPageNumber.
+   See documentation (mozbugbox)
+
+OTHER ENHANCEMENTS:
+
+ - Enhanced type handling (Brent Amrhein)
+
+ - Enhanced exception handling in NameObject (sbywater)
+
+ - Enhanced extractText method output (peircej)
+
+ - Better exception handling
+
+ - Enhanced regex usage in NameObject class (speedplane)
+
+
+Version 1.24, 2014-12-31
 ------------------------
 
  - Bugfixes for reading files in Python 3 (by Anthony Tuininga and
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/PyPDF2/_version.py 
new/PyPDF2-1.26.0/PyPDF2/_version.py
--- old/PyPDF2-1.24/PyPDF2/_version.py  2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/PyPDF2/_version.py        2016-05-18 18:47:24.000000000 
+0200
@@ -1 +1 @@
-__version__ = '1.24'
+__version__ = '1.26.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/PyPDF2/filters.py 
new/PyPDF2-1.26.0/PyPDF2/filters.py
--- old/PyPDF2-1.24/PyPDF2/filters.py   2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/PyPDF2/filters.py 2016-05-18 18:47:24.000000000 +0200
@@ -40,6 +40,7 @@
     from cStringIO import StringIO
 else:
     from io import StringIO
+    import struct
 
 try:
     import zlib
@@ -256,55 +257,78 @@
 
 class ASCII85Decode(object):
     def decode(data, decodeParms=None):
-        retval = ""
-        group = []
-        x = 0
-        hitEod = False
-        # remove all whitespace from data
-        data = [y for y in data if not (y in ' \n\r\t')]
-        while not hitEod:
-            c = data[x]
-            if len(retval) == 0 and c == "<" and data[x+1] == "~":
-                x += 2
-                continue
-            #elif c.isspace():
-            #    x += 1
-            #    continue
-            elif c == 'z':
-                assert len(group) == 0
-                retval += '\x00\x00\x00\x00'
-                x += 1
-                continue
-            elif c == "~" and data[x+1] == ">":
-                if len(group) != 0:
-                    # cannot have a final group of just 1 char
-                    assert len(group) > 1
-                    cnt = len(group) - 1
-                    group += [ 85, 85, 85 ]
-                    hitEod = cnt
+        if version_info < ( 3, 0 ):
+            retval = ""
+            group = []
+            x = 0
+            hitEod = False
+            # remove all whitespace from data
+            data = [y for y in data if not (y in ' \n\r\t')]
+            while not hitEod:
+                c = data[x]
+                if len(retval) == 0 and c == "<" and data[x+1] == "~":
+                    x += 2
+                    continue
+                #elif c.isspace():
+                #    x += 1
+                #    continue
+                elif c == 'z':
+                    assert len(group) == 0
+                    retval += '\x00\x00\x00\x00'
+                    x += 1
+                    continue
+                elif c == "~" and data[x+1] == ">":
+                    if len(group) != 0:
+                        # cannot have a final group of just 1 char
+                        assert len(group) > 1
+                        cnt = len(group) - 1
+                        group += [ 85, 85, 85 ]
+                        hitEod = cnt
+                    else:
+                        break
                 else:
+                    c = ord(c) - 33
+                    assert c >= 0 and c < 85
+                    group += [ c ]
+                if len(group) >= 5:
+                    b = group[0] * (85**4) + \
+                        group[1] * (85**3) + \
+                        group[2] * (85**2) + \
+                        group[3] * 85 + \
+                        group[4]
+                    assert b < (2**32 - 1)
+                    c4 = chr((b >> 0) % 256)
+                    c3 = chr((b >> 8) % 256)
+                    c2 = chr((b >> 16) % 256)
+                    c1 = chr(b >> 24)
+                    retval += (c1 + c2 + c3 + c4)
+                    if hitEod:
+                        retval = retval[:-4+hitEod]
+                    group = []
+                x += 1
+            return retval
+        else:
+            if isinstance(data, str):
+                data = data.encode('ascii')
+            n = b = 0
+            out = bytearray()
+            for c in data:
+                if ord('!') <= c and c <= ord('u'):
+                    n += 1
+                    b = b*85+(c-33)
+                    if n == 5:
+                        out += struct.pack(b'>L',b)
+                        n = b = 0
+                elif c == ord('z'):
+                    assert n == 0
+                    out += b'\0\0\0\0'
+                elif c == ord('~'):
+                    if n:
+                        for _ in range(5-n):
+                            b = b*85+84
+                        out += struct.pack(b'>L',b)[:n-1]
                     break
-            else:
-                c = ord(c) - 33
-                assert c >= 0 and c < 85
-                group += [ c ]
-            if len(group) >= 5:
-                b = group[0] * (85**4) + \
-                    group[1] * (85**3) + \
-                    group[2] * (85**2) + \
-                    group[3] * 85 + \
-                    group[4]
-                assert b < (2**32 - 1)
-                c4 = chr((b >> 0) % 256)
-                c3 = chr((b >> 8) % 256)
-                c2 = chr((b >> 16) % 256)
-                c1 = chr(b >> 24)
-                retval += (c1 + c2 + c3 + c4)
-                if hitEod:
-                    retval = retval[:-4+hitEod]
-                group = []
-            x += 1
-        return retval
+            return bytes(out)
     decode = staticmethod(decode)
 
 
@@ -315,22 +339,24 @@
         # we have a single filter instance
         filters = (filters,)
     data = stream._data
-    for filterType in filters:
-        if filterType == "/FlateDecode":
-            data = FlateDecode.decode(data, stream.get("/DecodeParms"))
-        elif filterType == "/ASCIIHexDecode":
-            data = ASCIIHexDecode.decode(data)
-        elif filterType == "/LZWDecode":
-            data = LZWDecode.decode(data, stream.get("/DecodeParms"))
-        elif filterType == "/ASCII85Decode":
-            data = ASCII85Decode.decode(data)
-        elif filterType == "/Crypt":
-            decodeParams = stream.get("/DecodeParams", {})
-            if "/Name" not in decodeParams and "/Type" not in decodeParams:
-                pass
+    # If there is not data to decode we should not try to decode the data.
+    if data:
+        for filterType in filters:
+            if filterType == "/FlateDecode" or filterType == "/Fl":
+                data = FlateDecode.decode(data, stream.get("/DecodeParms"))
+            elif filterType == "/ASCIIHexDecode" or filterType == "/AHx":
+                data = ASCIIHexDecode.decode(data)
+            elif filterType == "/LZWDecode" or filterType == "/LZW":
+                data = LZWDecode.decode(data, stream.get("/DecodeParms"))
+            elif filterType == "/ASCII85Decode" or filterType == "/A85":
+                data = ASCII85Decode.decode(data)
+            elif filterType == "/Crypt":
+                decodeParams = stream.get("/DecodeParams", {})
+                if "/Name" not in decodeParams and "/Type" not in decodeParams:
+                    pass
+                else:
+                    raise NotImplementedError("/Crypt filter with /Name or 
/Type not supported yet")
             else:
-                raise NotImplementedError("/Crypt filter with /Name or /Type 
not supported yet")
-        else:
-            # unsupported filter
-            raise NotImplementedError("unsupported filter %s" % filterType)
+                # unsupported filter
+                raise NotImplementedError("unsupported filter %s" % filterType)
     return data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/PyPDF2/generic.py 
new/PyPDF2-1.26.0/PyPDF2/generic.py
--- old/PyPDF2-1.24/PyPDF2/generic.py   2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/PyPDF2/generic.py 2016-05-18 18:47:24.000000000 +0200
@@ -43,6 +43,7 @@
 from . import utils
 import decimal
 import codecs
+import sys
 #import debugging
 
 ObjectPrefix = b_('/<[tf(n%')
@@ -233,8 +234,12 @@
         if self == self.to_integral():
             return str(self.quantize(decimal.Decimal(1)))
         else:
-            # XXX: this adds useless extraneous zeros.
-            return "%.5f" % self
+            # Standard formatting adds useless extraneous zeros.
+            o = "%.5f" % self
+            # Remove the zeros.
+            while o and o[-1] == '0':
+                o = o[:-1]
+            return o
 
     def as_numeric(self):
         return float(b_(repr(self)))
@@ -248,7 +253,11 @@
     ByteDot = b_(".")
 
     def __new__(cls, value):
-        return int.__new__(cls, value)
+        val = int(value)
+        try:
+            return int.__new__(cls, val)
+        except OverflowError:
+            return int.__new__(cls, 0)
 
     def as_numeric(self):
         return int(b_(repr(self)))
@@ -340,13 +349,18 @@
                 tok = b_("\b")
             elif tok == b_("f"):
                 tok = b_("\f")
+            elif tok == b_("c"):
+                tok = b_("\c")
             elif tok == b_("("):
                 tok = b_("(")
             elif tok == b_(")"):
                 tok = b_(")")
+            elif tok == b_("/"):
+                tok = b_("/")
             elif tok == b_("\\"):
                 tok = b_("\\")
-            elif tok in (b_(" "), b_("/"), b_("%"), b_("<"), b_(">"), b_("["), 
b_("]")):
+            elif tok in (b_(" "), b_("/"), b_("%"), b_("<"), b_(">"), b_("["), 
+                    b_("]"), b_("#"),  b_("_"), b_("&"), b_('$')):
                 # odd/unnessecary escape sequences we have encountered
                 tok = b_(tok)
             elif tok.isdigit():
@@ -373,7 +387,7 @@
                 # line break was escaped:
                 tok = b_('')
             else:
-                raise utils.PdfReadError("Unexpected escaped string")
+                raise utils.PdfReadError(r"Unexpected escaped string: %s" % 
tok)
         txt += tok
     return createStringObject(txt)
 
@@ -451,7 +465,7 @@
 
 
 class NameObject(str, PdfObject):
-    delimiterPattern = re.compile(b_("\s+|[()<>[\]{}/%]"))
+    delimiterPattern = re.compile(b_(r"\s+|[\(\)<>\[\]{}/%]"))
     surfix = b_("/")
 
     def writeToStream(self, stream, encryption_key):
@@ -463,11 +477,12 @@
         name = stream.read(1)
         if name != NameObject.surfix:
             raise utils.PdfReadError("name read error")
-        name += utils.readUntilRegex(stream, NameObject.delimiterPattern)
+        name += utils.readUntilRegex(stream, NameObject.delimiterPattern, 
+            ignore_eof=True)
         if debug: print(name)
         try:
             return NameObject(name.decode('utf-8'))
-        except UnicodeDecodeError as e:
+        except (UnicodeEncodeError, UnicodeDecodeError) as e:
             # Name objects should represent irregular characters
             # with a '#' followed by the symbol's hex number
             if not pdf.strict:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/PyPDF2/merger.py 
new/PyPDF2-1.26.0/PyPDF2/merger.py
--- old/PyPDF2-1.24/PyPDF2/merger.py    2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/PyPDF2/merger.py  2016-05-18 18:47:24.000000000 +0200
@@ -28,7 +28,7 @@
 # POSSIBILITY OF SUCH DAMAGE.
 
 from .generic import *
-from .utils import string_type, str_
+from .utils import isString, str_
 from .pdf import PdfFileReader, PdfFileWriter
 from .pagerange import PageRange
 from sys import version_info
@@ -109,7 +109,8 @@
         # it is a PdfFileReader, copy that reader's stream into a
         # BytesIO (or StreamIO) stream.
         # If fileobj is none of the above types, it is not modified
-        if type(fileobj) == string_type:
+        decryption_key = None
+        if isString(fileobj):
             fileobj = file(fileobj, 'rb')
             my_file = True
         elif isinstance(fileobj, file):
@@ -123,11 +124,15 @@
             filecontent = StreamIO(fileobj.stream.read())
             fileobj.stream.seek(orig_tell) # reset the stream to its original 
location
             fileobj = filecontent
+            if hasattr(fileobj, '_decryption_key'):
+                decryption_key = fileobj._decryption_key
             my_file = True
 
         # Create a new PdfFileReader instance using the stream
         # (either file or BytesIO or StringIO) created above
         pdfr = PdfFileReader(fileobj, strict=self.strict)
+        if decryption_key is not None:
+            pdfr._decryption_key = decryption_key
 
         # Find the range of pages to merge.
         if pages == None:
@@ -205,7 +210,7 @@
             file-like object.
         """
         my_file = False
-        if type(fileobj) in (str, str):
+        if isString(fileobj):
             fileobj = file(fileobj, 'wb')
             my_file = True
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/PyPDF2/pagerange.py 
new/PyPDF2-1.26.0/PyPDF2/pagerange.py
--- old/PyPDF2-1.24/PyPDF2/pagerange.py 2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/PyPDF2/pagerange.py       2016-05-18 18:47:24.000000000 
+0200
@@ -8,7 +8,7 @@
 """
 
 import re
-from .utils import Str
+from .utils import isString
 
 _INT_RE = r"(0|-?[1-9]\d*)"  # A decimal int, don't allow "-0".
 PAGE_RANGE_RE = "^({int}|({int}?(:{int}?(:{int}?)?)))$".format(int=_INT_RE)
@@ -68,7 +68,7 @@
             self._slice = arg.to_slice()
             return
 
-        m = isinstance(arg, Str) and re.match(PAGE_RANGE_RE, arg)
+        m = isString(arg) and re.match(PAGE_RANGE_RE, arg)
         if not m:
             raise ParseError(arg)
         elif m.group(2):
@@ -89,7 +89,7 @@
         """ True if input is a valid initializer for a PageRange. """
         return isinstance(input, slice)  or \
                isinstance(input, PageRange) or \
-               (isinstance(input, Str)
+               (isString(input)
                 and bool(re.match(PAGE_RANGE_RE, input)))
 
     def to_slice(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/PyPDF2/pdf.py 
new/PyPDF2-1.26.0/PyPDF2/pdf.py
--- old/PyPDF2-1.24/PyPDF2/pdf.py       2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/PyPDF2/pdf.py     2016-05-18 18:47:24.000000000 +0200
@@ -46,6 +46,7 @@
 import math
 import struct
 import sys
+import uuid
 from sys import version_info
 if version_info < ( 3, 0 ):
     from cStringIO import StringIO
@@ -63,7 +64,7 @@
 import codecs
 from .generic import *
 from .utils import readNonWhitespace, readUntilWhitespace, 
ConvertFunctionsToVirtualList
-from .utils import Str, b_, u_, ord_, chr_, str_, string_type, formatWarning
+from .utils import isString, b_, u_, ord_, chr_, str_, formatWarning
 
 if version_info < ( 2, 4 ):
    from sets import ImmutableSet as frozenset
@@ -225,10 +226,175 @@
                 NameObject("/S"): NameObject("/JavaScript"),
                 NameObject("/JS"): NameObject("(%s)" % javascript)
                 })
+        js_indirect_object = self._addObject(js)
+
+        # We need a name for parameterized javascript in the pdf file, but it 
can be anything.
+        js_string_name = str(uuid.uuid4())
+
+        js_name_tree = DictionaryObject()
+        js_name_tree.update({
+                NameObject("/JavaScript"): DictionaryObject({
+                  NameObject("/Names"): 
ArrayObject([createStringObject(js_string_name), js_indirect_object])
+                })
+              })
+        self._addObject(js_name_tree)
+
+        self._root_object.update({
+                NameObject("/OpenAction"): js_indirect_object,
+                NameObject("/Names"): js_name_tree
+                })
+
+    def addAttachment(self, fname, fdata):
+        """
+        Embed a file inside the PDF.
+
+        :param str fname: The filename to display.
+        :param str fdata: The data in the file.
+      
+        Reference:
+        
https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
+        Section 7.11.3
+        """
+        
+        # We need 3 entries:
+        # * The file's data
+        # * The /Filespec entry
+        # * The file's name, which goes in the Catalog
+        
+
+        # The entry for the file
+        """ Sample:
+        8 0 obj
+        <<
+         /Length 12
+         /Type /EmbeddedFile
+        >>
+        stream
+        Hello world!
+        endstream
+        endobj        
+        """
+        file_entry = DecodedStreamObject()
+        file_entry.setData(fdata)
+        file_entry.update({
+                NameObject("/Type"): NameObject("/EmbeddedFile")
+                })
+
+        # The Filespec entry
+        """ Sample:
+        7 0 obj
+        <<
+         /Type /Filespec
+         /F (hello.txt)
+         /EF << /F 8 0 R >>
+        >>
+        """
+        efEntry = DictionaryObject()
+        efEntry.update({ NameObject("/F"):file_entry })
+        
+        filespec = DictionaryObject()
+        filespec.update({
+                NameObject("/Type"): NameObject("/Filespec"),
+                NameObject("/F"): createStringObject(fname),  # Perhaps also 
try TextStringObject
+                NameObject("/EF"): efEntry
+                })
+                
+        # Then create the entry for the root, as it needs a reference to the 
Filespec
+        """ Sample:
+        1 0 obj
+        <<
+         /Type /Catalog
+         /Outlines 2 0 R
+         /Pages 3 0 R
+         /Names << /EmbeddedFiles << /Names [(hello.txt) 7 0 R] >> >>
+        >>
+        endobj
+        
+        """
+        embeddedFilesNamesDictionary = DictionaryObject()
+        embeddedFilesNamesDictionary.update({
+                NameObject("/Names"): ArrayObject([createStringObject(fname), 
filespec])
+                })
+        
+        embeddedFilesDictionary = DictionaryObject()
+        embeddedFilesDictionary.update({
+                NameObject("/EmbeddedFiles"): embeddedFilesNamesDictionary
+                })
+        # Update the root
         self._root_object.update({
-                NameObject("/OpenAction"): self._addObject(js)
+                NameObject("/Names"): embeddedFilesDictionary
                 })
 
+    def appendPagesFromReader(self, reader, after_page_append=None):
+        """
+        Copy pages from reader to writer. Includes an optional callback 
parameter
+        which is invoked after pages are appended to the writer.
+        
+        :param reader: a PdfFileReader object from which to copy page
+            annotations to this writer object.  The writer's annots
+        will then be updated
+        :callback after_page_append (function): Callback function that is 
invoked after
+            each page is appended to the writer. Callback signature:
+
+            :param writer_pageref (PDF page reference): Reference to the page
+                appended to the writer.
+        """
+        # Get page count from writer and reader
+        reader_num_pages = reader.getNumPages()
+        writer_num_pages = self.getNumPages()
+
+        # Copy pages from reader to writer
+        for rpagenum in range(0, reader_num_pages):
+            reader_page = reader.getPage(rpagenum)
+            self.addPage(reader_page)
+            writer_page = self.getPage(writer_num_pages+rpagenum)
+            # Trigger callback, pass writer page as parameter
+            if callable(after_page_append): after_page_append(writer_page)
+
+    def updatePageFormFieldValues(self, page, fields):
+        '''
+        Update the form field values for a given page from a fields dictionary.
+        Copy field texts and values from fields to page.
+
+        :param page: Page reference from PDF writer where the annotations
+            and field data will be updated.
+        :param fields: a Python dictionary of field names (/T) and text
+            values (/V)
+        '''
+        # Iterate through pages, update field values
+        for j in range(0, len(page['/Annots'])):
+            writer_annot = page['/Annots'][j].getObject()
+            for field in fields:
+                if writer_annot.get('/T') == field:
+                    writer_annot.update({
+                        NameObject("/V"): TextStringObject(fields[field])
+                    })
+
+    def cloneReaderDocumentRoot(self, reader):
+        '''
+        Copy the reader document root to the writer.
+        
+        :param reader:  PdfFileReader from the document root should be copied.
+        :callback after_page_append
+        '''
+        self._root_object = reader.trailer['/Root']
+
+    def cloneDocumentFromReader(self, reader, after_page_append=None):
+        '''
+        Create a copy (clone) of a document from a PDF file reader
+
+        :param reader: PDF file reader instance from which the clone
+            should be created.
+        :callback after_page_append (function): Callback function that is 
invoked after
+            each page is appended to the writer. Signature includes a 
reference to the
+            appended page (delegates to appendPagesFromReader). Callback 
signature:
+
+            :param writer_pageref (PDF page reference): Reference to the page 
just
+                appended to the document.
+        '''
+        self.cloneReaderDocumentRoot(reader)
+        self.appendPagesFromReader(reader, after_page_append)
+
     def encrypt(self, user_pwd, owner_pwd = None, use_128bit = True):
         """
         Encrypt this PDF file with the PDF Standard encryption handler.
@@ -407,18 +573,22 @@
             else:
                 newobj = externMap.get(data.pdf, {}).get(data.generation, 
{}).get(data.idnum, None)
                 if newobj == None:
-                    newobj = data.pdf.getObject(data)
-                    self._objects.append(None) # placeholder
-                    idnum = len(self._objects)
-                    newobj_ido = IndirectObject(idnum, 0, self)
-                    if data.pdf not in externMap:
-                        externMap[data.pdf] = {}
-                    if data.generation not in externMap[data.pdf]:
-                        externMap[data.pdf][data.generation] = {}
-                    externMap[data.pdf][data.generation][data.idnum] = 
newobj_ido
-                    newobj = self._sweepIndirectReferences(externMap, newobj)
-                    self._objects[idnum-1] = newobj
-                    return newobj_ido
+                    try:
+                        newobj = data.pdf.getObject(data)
+                        self._objects.append(None) # placeholder
+                        idnum = len(self._objects)
+                        newobj_ido = IndirectObject(idnum, 0, self)
+                        if data.pdf not in externMap:
+                            externMap[data.pdf] = {}
+                        if data.generation not in externMap[data.pdf]:
+                            externMap[data.pdf][data.generation] = {}
+                        externMap[data.pdf][data.generation][data.idnum] = 
newobj_ido
+                        newobj = self._sweepIndirectReferences(externMap, 
newobj)
+                        self._objects[idnum-1] = newobj
+                        return newobj_ido
+                    except ValueError:
+                        # Unable to resolve the Object, returning NullObject 
instead.
+                        return NullObject()
                 return newobj
         else:
             return data
@@ -758,7 +928,7 @@
         else:
             borderArr = [NumberObject(0)] * 3
 
-        if isinstance(rect, Str):
+        if isString(rect):
             rect = NameObject(rect)
         elif isinstance(rect, RectangleObject):
             pass
@@ -904,9 +1074,10 @@
         self.flattenedPages = None
         self.resolvedObjects = {}
         self.xrefIndex = 0
+        self._pageId2Num = None # map page IndirectRef number to Page Number
         if hasattr(stream, 'mode') and 'b' not in stream.mode:
             warnings.warn("PdfFileReader stream/file object is not in binary 
mode. It may not be read correctly.", utils.PdfReadWarning)
-        if type(stream) in (string_type, str):
+        if isString(stream):
             fileobj = open(stream, 'rb')
             stream = BytesIO(b_(fileobj.read()))
             fileobj.close()
@@ -973,6 +1144,7 @@
         if self.isEncrypted:
             try:
                 self._override_encryption = True
+                self.decrypt('')
                 return self.trailer["/Root"]["/Pages"]["/Count"]
             except:
                 raise utils.PdfReadError("File has not been decrypted")
@@ -1101,6 +1273,16 @@
                 # Field attribute is N/A or unknown, so don't write anything
                 pass
 
+    def getFormTextFields(self):
+        ''' Retrieves form fields from the document with textual data (inputs, 
dropdowns)
+        '''
+        # Retrieve document form fields
+        formfields = self.getFields()
+        return dict(
+            (formfields[field]['/T'], formfields[field].get('/V')) for field 
in formfields \
+                if formfields[field].get('/FT') == '/Tx'
+        )
+
     def getNamedDestinations(self, tree=None, retval=None):
         """
         Retrieves the named destinations present in the document.
@@ -1167,7 +1349,7 @@
                     # for an example of such a file, see 
https://unglueit-files.s3.amazonaws.com/ebf/7552c42e9280b4476e59e77acc0bc812.pdf
                     # so continue to load the file without the Bookmarks
                     return outlines
-                    
+
                 if "/First" in lines:
                     node = lines["/First"]
             self._namedDests = self.getNamedDestinations()
@@ -1194,6 +1376,49 @@
 
         return outlines
 
+    def _getPageNumberByIndirect(self, indirectRef):
+        """Generate _pageId2Num"""
+        if self._pageId2Num is None:
+            id2num = {}
+            for i, x in enumerate(self.pages):
+                id2num[x.indirectRef.idnum] = i
+            self._pageId2Num = id2num
+
+        if isinstance(indirectRef, int):
+            idnum = indirectRef
+        else:
+            idnum = indirectRef.idnum
+
+        ret = self._pageId2Num.get(idnum, -1)
+        return ret
+
+    def getPageNumber(self, page):
+        """
+        Retrieve page number of a given PageObject
+
+        :param PageObject page: The page to get page number. Should be
+            an instance of :class:`PageObject<PyPDF2.pdf.PageObject>`
+        :return: the page number or -1 if page not found
+        :rtype: int
+        """
+        indirectRef = page.indirectRef
+        ret = self._getPageNumberByIndirect(indirectRef)
+        return ret
+
+    def getDestinationPageNumber(self, destination):
+        """
+        Retrieve page number of a given Destination object
+
+        :param Destination destination: The destination to get page number.
+             Should be an instance of
+             :class:`Destination<PyPDF2.pdf.Destination>`
+        :return: the page number or -1 if page not found
+        :rtype: int
+        """
+        indirectRef = destination.page
+        ret = self._getPageNumberByIndirect(indirectRef)
+        return ret
+
     def _buildDestination(self, title, array):
         page, typ = array[0:2]
         array = array[2:]
@@ -1217,7 +1442,7 @@
         if dest:
             if isinstance(dest, ArrayObject):
                 outline = self._buildDestination(title, dest)
-            elif isinstance(dest, Str) and dest in self._namedDests:
+            elif isString(dest) and dest in self._namedDests:
                 outline = self._namedDests[dest]
                 outline[NameObject("/Title")] = title
             else:
@@ -1317,6 +1542,8 @@
         assert idx < objStm['/N']
         streamData = BytesIO(b_(objStm.getData()))
         for i in range(objStm['/N']):
+            readNonWhitespace(streamData)
+            streamData.seek(-1, 1)
             objnum = NumberObject.readFromStream(streamData)
             readNonWhitespace(streamData)
             streamData.seek(-1, 1)
@@ -1505,10 +1732,10 @@
                     num = readObject(stream, self)
                     if firsttime and num != 0:
                          self.xrefIndex = num
-                         warnings.warn("Xref table not zero-indexed. ID 
numbers for objects will %sbe corrected." % \
-                                       ("" if not self.strict else "not "), 
utils.PdfReadWarning)
-                         #if table not zero indexed, could be due to error 
from when PDF was created
-                         #which will lead to mismatched indices later on
+                         if self.strict:
+                            warnings.warn("Xref table not zero-indexed. ID 
numbers for objects will be corrected.", utils.PdfReadWarning)
+                            #if table not zero indexed, could be due to error 
from when PDF was created
+                            #which will lead to mismatched indices later on, 
only warned and corrected if self.strict=True
                     firsttime = False
                     readNonWhitespace(stream)
                     stream.seek(-1, 1)
@@ -1671,8 +1898,7 @@
                 if found:
                     continue
                 # no xref table found at specified location
-                assert False
-                break
+                raise utils.PdfReadError("Could not find xref table at 
specified location")
         #if not zero-indexed, verify that the table is correct; change it if 
necessary
         if self.xrefIndex and not self.strict:
             loc = stream.tell()
@@ -1945,7 +2171,7 @@
         page2Res = res2.get(resource, DictionaryObject()).getObject()
         renameRes = {}
         for key in list(page2Res.keys()):
-            if key in newRes and newRes[key] != page2Res[key]:
+            if key in newRes and newRes.raw_get(key) != page2Res.raw_get(key):
                 newname = NameObject(key + str(uuid.uuid4()))
                 renameRes[key] = newname
                 newRes[newname] = page2Res[key]
@@ -2391,6 +2617,7 @@
                 for i in operands[0]:
                     if isinstance(i, TextStringObject):
                         text += i
+                text += "\n"
         return text
 
     mediaBox = createRectangleAccessor("/MediaBox", ())
@@ -2498,38 +2725,45 @@
         assert tmp[:2] == b_("ID")
         data = b_("")
         while True:
+            # Read the inline image, while checking for EI (End Image) 
operator.
             tok = stream.read(1)
             if tok == b_("E"):
                 # Check for End Image
-                next1 = stream.read(1)
-                if next1 == b_("I"):
-                    next2 = readNonWhitespace(stream)
-                    if next2 == b_('Q'):
+                tok2 = stream.read(1)
+                if tok2 == b_("I"):
+                    # Data can contain EI, so check for the Q operator.
+                    tok3 = stream.read(1)
+                    info = tok + tok2
+                    # We need to find whitespace between EI and Q.
+                    has_q_whitespace = False
+                    while tok3 in utils.WHITESPACES:
+                        has_q_whitespace = True
+                        info += tok3
+                        tok3 = stream.read(1)
+                    if tok3 == b_("Q") and has_q_whitespace:
                         stream.seek(-1, 1)
                         break
                     else:
-                        stream.seek(-2, 1)
-                        data += tok
+                        stream.seek(-1,1)
+                        data += info
                 else:
                     stream.seek(-1, 1)
                     data += tok
             else:
                 data += tok
-        readNonWhitespace(stream)
-        stream.seek(-1, 1)
         return {"settings": settings, "data": data}
 
     def _getData(self):
         newdata = BytesIO()
         for operands, operator in self.operations:
-            if operator == "INLINE IMAGE":
-                newdata.write("BI")
-                dicttext = StringIO()
+            if operator == b_("INLINE IMAGE"):
+                newdata.write(b_("BI"))
+                dicttext = BytesIO()
                 operands["settings"].writeToStream(dicttext, None)
                 newdata.write(dicttext.getvalue()[2:-2])
-                newdata.write("ID ")
+                newdata.write(b_("ID "))
                 newdata.write(operands["data"])
-                newdata.write("EI")
+                newdata.write(b_("EI"))
             else:
                 for op in operands:
                     op.writeToStream(newdata, None)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/PyPDF2/utils.py 
new/PyPDF2-1.26.0/PyPDF2/utils.py
--- old/PyPDF2-1.24/PyPDF2/utils.py     2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/PyPDF2/utils.py   2016-05-18 18:47:24.000000000 +0200
@@ -33,25 +33,35 @@
 
 
 import sys
-# "Str" maintains compatibility with Python 2.x.
-# The next line is obfuscated like this so 2to3 won't change it.
+
 try:
     import __builtin__ as builtins
 except ImportError:  # Py3
     import builtins
 
 
-if sys.version_info[0] < 3:
-    string_type = unicode
-    bytes_type = str
-    int_types = (int, long)
-else:
-    string_type = str
-    bytes_type = bytes
-    int_types = (int,)
+xrange_fn = getattr(builtins, "xrange", range)
+_basestring = getattr(builtins, "basestring", str)
+
+bytes_type = type(bytes()) # Works the same in Python 2.X and 3.X
+string_type = getattr(builtins, "unicode", str)
+int_types = (int, long) if sys.version_info[0] < 3 else (int,)
+
+
+# Make basic type tests more consistent
+def isString(s):
+    """Test if arg is a string. Compatible with Python 2 and 3."""
+    return isinstance(s, _basestring)
+
+
+def isInt(n):
+    """Test if arg is an int. Compatible with Python 2 and 3."""
+    return isinstance(n, int_types)
+
 
-Xrange = getattr(builtins, "xrange", range)
-Str = getattr(builtins, "basestring", str)
+def isBytes(b):
+    """Test if arg is a bytes instance. Compatible with Python 2 and 3."""
+    return isinstance(b, bytes_type)
 
 
 #custom implementation of warnings.formatwarning
@@ -141,10 +151,10 @@
 
     def __getitem__(self, index):
         if isinstance(index, slice):
-            indices = Xrange(*index.indices(len(self)))
+            indices = xrange_fn(*index.indices(len(self)))
             cls = type(self)
             return cls(indices.__len__, lambda idx: self[indices[idx]])
-        if not isinstance(index, int_types):
+        if not isInt(index):
             raise TypeError("sequence indices must be integers")
         len_self = len(self)
         if index < 0:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/README.md new/PyPDF2-1.26.0/README.md
--- old/PyPDF2-1.24/README.md   2014-12-31 22:45:23.000000000 +0100
+++ new/PyPDF2-1.26.0/README.md 2016-05-18 18:47:24.000000000 +0200
@@ -23,3 +23,12 @@
 ##FAQ
 Please see  
 http://mstamy2.github.io/PyPDF2/FAQ.html
+
+
+##Tests
+PyPDF2 includes a test suite built on the unittest framework. All tests are 
located in the "Tests" folder.
+Tests can be run from the command line by:
+
+```bash
+python -m unittest Tests.tests
+```
\ No newline at end of file
Binary files old/PyPDF2-1.24/Resources/crazyones.pdf and 
new/PyPDF2-1.26.0/Resources/crazyones.pdf differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/Resources/crazyones.txt 
new/PyPDF2-1.26.0/Resources/crazyones.txt
--- old/PyPDF2-1.24/Resources/crazyones.txt     1970-01-01 01:00:00.000000000 
+0100
+++ new/PyPDF2-1.26.0/Resources/crazyones.txt   2016-05-18 18:47:24.000000000 
+0200
@@ -0,0 +1 @@
+TheCrazyOnesOctober14,1998Herestothecrazyones.Themis˝ts.Therebels.Thetroublemakers.Theroundpegsinthesquareholes.Theoneswhoseethingsdi˙erently.Theyrenotfondofrules.Andtheyhavenorespectforthestatusquo.Youcanquotethem,disagreewiththem,glorifyorvilifythem.Abouttheonlythingyoucantdoisignorethem.Becausetheychangethings.Theyinvent.Theyimagine.Theyheal.Theyexplore.Theycreate.Theyinspire.Theypushthehumanraceforward.Maybetheyhavetobecrazy.Howelsecanyoustareatanemptycanvasandseeaworkofart?Orsitinsilenceandhearasongthatsneverbeenwritten?Orgazeataredplanetandseealaboratoryonwheels?Wemaketoolsforthesekindsofpeople.Whilesomeseethemasthecrazyones,weseegenius.Becausethepeoplewhoarecrazyenoughtothinktheycanchangetheworld,aretheoneswhodo.
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/PyPDF2-1.24/Tests/tests.py 
new/PyPDF2-1.26.0/Tests/tests.py
--- old/PyPDF2-1.24/Tests/tests.py      1970-01-01 01:00:00.000000000 +0100
+++ new/PyPDF2-1.26.0/Tests/tests.py    2016-05-18 18:47:24.000000000 +0200
@@ -0,0 +1,69 @@
+import os
+import sys
+import unittest
+
+from PyPDF2 import PdfFileReader, PdfFileWriter
+
+
+# Configure path environment
+TESTS_ROOT = os.path.abspath(os.path.dirname(__file__))
+PROJECT_ROOT = os.path.dirname(TESTS_ROOT)
+RESOURCE_ROOT = os.path.join(PROJECT_ROOT, 'Resources')
+
+sys.path.append(PROJECT_ROOT)
+
+
+class PdfReaderTestCases(unittest.TestCase):
+
+    def test_PdfReaderFileLoad(self):
+        '''
+        Test loading and parsing of a file. Extract text of the file and 
compare to expected
+        textual output. Expected outcome: file loads, text matches expected.
+        '''
+
+        with open(os.path.join(RESOURCE_ROOT, 'crazyones.pdf'), 'rb') as 
inputfile:
+            # Load PDF file from file
+            ipdf = PdfFileReader(inputfile)
+            ipdf_p1 = ipdf.getPage(0)
+
+            # Retrieve the text of the PDF
+            pdftext_file = open(os.path.join(RESOURCE_ROOT, 'crazyones.txt'), 
'r')
+            pdftext = pdftext_file.read()
+            ipdf_p1_text = ipdf_p1.extractText().replace('\n', '')
+
+            # Compare the text of the PDF to a known source
+            self.assertEqual(ipdf_p1_text.encode('utf-8', errors='ignore'), 
pdftext,
+                msg='PDF extracted text differs from expected 
value.\n\nExpected:\n\n%r\n\nExtracted:\n\n%r\n\n'
+                    % (pdftext, ipdf_p1_text.encode('utf-8', errors='ignore')))
+
+
+class AddJsTestCase(unittest.TestCase):
+
+    def setUp(self):
+        ipdf = PdfFileReader(os.path.join(RESOURCE_ROOT, 'crazyones.pdf'))
+        self.pdf_file_writer = PdfFileWriter()
+        self.pdf_file_writer.appendPagesFromReader(ipdf)
+
+    def test_add(self):
+
+        
self.pdf_file_writer.addJS("this.print({bUI:true,bSilent:false,bShrinkToFit:true});")
+
+        self.assertIn('/Names', self.pdf_file_writer._root_object, "addJS 
should add a name catalog in the root object.")
+        self.assertIn('/JavaScript', 
self.pdf_file_writer._root_object['/Names'], "addJS should add a JavaScript 
name tree under the name catalog.")
+        self.assertIn('/OpenAction', self.pdf_file_writer._root_object, "addJS 
should add an OpenAction to the catalog.")
+
+    def test_overwrite(self):
+
+        
self.pdf_file_writer.addJS("this.print({bUI:true,bSilent:false,bShrinkToFit:true});")
+        first_js = self.get_javascript_name()
+
+        
self.pdf_file_writer.addJS("this.print({bUI:true,bSilent:false,bShrinkToFit:true});")
+        second_js = self.get_javascript_name()
+
+        self.assertNotEqual(first_js, second_js, "addJS should overwrite the 
previous script in the catalog.")
+
+    def get_javascript_name(self):
+        self.assertIn('/Names', self.pdf_file_writer._root_object)
+        self.assertIn('/JavaScript', 
self.pdf_file_writer._root_object['/Names'])
+        self.assertIn('/Names', 
self.pdf_file_writer._root_object['/Names']['/JavaScript'])
+        return 
self.pdf_file_writer._root_object['/Names']['/JavaScript']['/Names'][0]


Reply via email to