From a0abf1ec097ba8a8bb3a2d27a14f3493b7f33821 Mon Sep 17 00:00:00 2001 From: Martin Thoma Date: Sat, 10 Dec 2022 16:25:08 +0100 Subject: [PATCH] =?UTF-8?q?MAINT:=20indirect=5Fref=20=E2=9E=94=20indirect?= =?UTF-8?q?=5Freference=20(#1484)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove xfail from passing test Don't consider deprecated code for coverage testing --- PyPDF2/_page.py | 25 ++++++++++++++++++++++--- PyPDF2/_reader.py | 6 +++--- PyPDF2/_writer.py | 24 ++++++++++++++++++------ pyproject.toml | 1 + tests/__init__.py | 2 +- tests/test_generic.py | 8 ++++---- tests/test_reader.py | 1 - tests/test_writer.py | 4 ++-- 8 files changed, 51 insertions(+), 20 deletions(-) diff --git a/PyPDF2/_page.py b/PyPDF2/_page.py index 52863407c..8ed755f3d 100644 --- a/PyPDF2/_page.py +++ b/PyPDF2/_page.py @@ -55,10 +55,10 @@ logger_warning, matrix_multiply, ) +from .constants import AnnotationDictionaryAttributes as ADA from .constants import ImageAttributes as IA from .constants import PageAttributes as PG from .constants import Ressources as RES -from .constants import AnnotationDictionaryAttributes as ADA from .errors import PageSizeNotDefinedError from .filters import _xobj_to_image from .generic import ( @@ -284,20 +284,39 @@ class PageObject(DictionaryObject): :meth:`create_blank_page()` static method. :param pdf: PDF file the page belongs to. - :param indirect_ref: Stores the original indirect reference to + :param indirect_reference: Stores the original indirect reference to this object in its source PDF """ def __init__( self, pdf: Optional[Any] = None, # PdfReader + indirect_reference: Optional[IndirectObject] = None, indirect_ref: Optional[IndirectObject] = None, ) -> None: from ._reader import PdfReader DictionaryObject.__init__(self) self.pdf: Optional[PdfReader] = pdf - self.indirect_ref = indirect_ref + if indirect_ref is not None: # deprecated + warnings.warn( + "Use indirect_reference instead of indirect_ref.", DeprecationWarning + ) + if indirect_reference is not None: + raise ValueError("Use indirect_reference instead of indirect_ref.") + indirect_reference = indirect_ref + self.indirect_reference = indirect_reference + + @property + def indirect_ref(self) -> Optional[IndirectObject]: # deprecated + warnings.warn( + "Use indirect_reference instead of indirect_ref.", DeprecationWarning + ) + return self.indirect_reference + + @indirect_ref.setter + def indirect_ref(self, value: Optional[IndirectObject]) -> None: # deprecated + self.indirect_reference = value def hash_value_data(self) -> bytes: data = super().hash_value_data() diff --git a/PyPDF2/_reader.py b/PyPDF2/_reader.py index a994b9ee1..b2b2a33a3 100644 --- a/PyPDF2/_reader.py +++ b/PyPDF2/_reader.py @@ -820,7 +820,7 @@ def _get_page_number_by_indirect( """Generate _page_id2num""" if self._page_id2num is None: self._page_id2num = { - x.indirect_ref.idnum: i for i, x in enumerate(self.pages) # type: ignore + x.indirect_reference.idnum: i for i, x in enumerate(self.pages) # type: ignore } if indirect_reference is None or isinstance(indirect_reference, NullObject): @@ -841,7 +841,7 @@ def get_page_number(self, page: PageObject) -> int: an instance of :class:`PageObject` :return: the page number or -1 if page not found """ - return self._get_page_number_by_indirect(page.indirect_ref) + return self._get_page_number_by_indirect(page.indirect_reference) def getPageNumber(self, page: PageObject) -> int: # pragma: no cover """ @@ -904,7 +904,7 @@ def _build_destination( if self.strict: raise # create a link to first Page - tmp = self.pages[0].indirect_ref + tmp = self.pages[0].indirect_reference indirect_reference = NullObject() if tmp is None else tmp return Destination( title, indirect_reference, TextStringObject("/Fit") # type: ignore diff --git a/PyPDF2/_writer.py b/PyPDF2/_writer.py index 0c5e77b90..5ba8e6f45 100644 --- a/PyPDF2/_writer.py +++ b/PyPDF2/_writer.py @@ -201,17 +201,25 @@ def _add_object(self, obj: PdfObject) -> IndirectObject: self._objects.append(obj) return IndirectObject(len(self._objects), 0, self) - def get_object(self, indirect_reference: Optional[IndirectObject] = None, ido: Optional[IndirectObject] = None) -> PdfObject: - if ido is not None: + def get_object( + self, + indirect_reference: Optional[IndirectObject] = None, + ido: Optional[IndirectObject] = None, + ) -> PdfObject: + if ido is not None: # deprecated if indirect_reference is not None: - raise ValueError("Please only set 'indirect_reference'. The 'ido' argument is deprecated.") + raise ValueError( + "Please only set 'indirect_reference'. The 'ido' argument is deprecated." + ) else: indirect_reference = ido warnings.warn( "The parameter 'ido' is depreciated and will be removed in PyPDF2 3.0.0.", DeprecationWarning, ) - assert indirect_reference is not None # the None value is only there to keep the deprecated name + assert ( + indirect_reference is not None + ) # the None value is only there to keep the deprecated name if indirect_reference.pdf != self: raise ValueError("pdf must be self") return self._objects[indirect_reference.idnum - 1] # type: ignore @@ -466,7 +474,9 @@ def open_destination(self, dest: Union[None, str, Destination, PageObject]) -> N elif isinstance(dest, PageObject): self._root_object[NameObject("/OpenAction")] = Destination( "Opening", - dest.indirect_ref if dest.indirect_ref is not None else NullObject(), + dest.indirect_reference + if dest.indirect_reference is not None + else NullObject(), TextStringObject("/Fit"), ).dest_array @@ -1402,7 +1412,9 @@ def add_outline(self) -> None: "This method is not yet implemented. Use :meth:`add_outline_item` instead." ) - def add_named_destination_object(self, page_destination: PdfObject) -> IndirectObject: + def add_named_destination_object( + self, page_destination: PdfObject + ) -> IndirectObject: page_destination_ref = self._add_object(page_destination) nd = self.get_named_dest_root() diff --git a/pyproject.toml b/pyproject.toml index 6bd92023d..78fceecfe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,6 +82,7 @@ exclude_lines = [ # Have to re-enable the standard pragma "pragma: no cover", "@overload", + "deprecated", # Don't complain about missing debug-only code: "def __repr__", diff --git a/tests/__init__.py b/tests/__init__.py index 3b4539cc7..7f34826bb 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -58,7 +58,7 @@ class ReaderDummy: def __init__(self, strict=False): self.strict = strict - def get_object(self, indirect_ref): + def get_object(self, indirect_reference): class DummyObj: def get_object(self): return self diff --git a/tests/test_generic.py b/tests/test_generic.py index f95c6708d..886e4d3f2 100644 --- a/tests/test_generic.py +++ b/tests/test_generic.py @@ -41,7 +41,7 @@ class ChildDummy(DictionaryObject): @property - def indirect_ref(self): + def indirect_reference(self): return self @@ -488,7 +488,7 @@ def test_remove_child_not_in_tree(): def test_remove_child_not_in_that_tree(): tree = TreeObject() - tree.indirect_ref = NullObject() + tree.indirect_reference = NullObject() # child = ChildDummy(TreeObject()) child = TreeObject() with pytest.raises(ValueError) as exc: @@ -503,11 +503,11 @@ def test_remove_child_not_in_that_tree(): def test_remove_child_not_found_in_tree(): class ChildDummy(DictionaryObject): @property - def indirect_ref(self): + def indirect_reference(self): return self tree = TreeObject() - tree.indirect_ref = NullObject() + tree.indirect_reference = NullObject() child = ChildDummy(TreeObject()) tree.add_child(child, ReaderDummy()) child2 = ChildDummy(TreeObject()) diff --git a/tests/test_reader.py b/tests/test_reader.py index bd8c58335..25018ae0f 100644 --- a/tests/test_reader.py +++ b/tests/test_reader.py @@ -769,7 +769,6 @@ def test_get_object(): assert reader._get_indirect_object(22, 0)["/Type"] == "/Catalog" -@pytest.mark.xfail(reason="#591") def test_extract_text_hello_world(): reader = PdfReader(RESOURCE_ROOT / "hello-world.pdf") text = reader.pages[0].extract_text().split("\n") diff --git a/tests/test_writer.py b/tests/test_writer.py index 1edc1aa5e..0e63b0aba 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -830,10 +830,10 @@ def test_startup_dest(): pdf_file_writer.open_destination = pdf_file_writer.pages[9] # checked also using Acrobrat to verify the good page is opened op = pdf_file_writer._root_object["/OpenAction"] - assert op[0] == pdf_file_writer.pages[9].indirect_ref + assert op[0] == pdf_file_writer.pages[9].indirect_reference assert op[1] == "/Fit" op = pdf_file_writer.open_destination - assert op.raw_get("/Page") == pdf_file_writer.pages[9].indirect_ref + assert op.raw_get("/Page") == pdf_file_writer.pages[9].indirect_reference assert op["/Type"] == "/Fit" pdf_file_writer.open_destination = op assert pdf_file_writer.open_destination == op