diff --git a/pypdf/_encryption.py b/pypdf/_encryption.py index 0eab7d971..dd4acbc42 100644 --- a/pypdf/_encryption.py +++ b/pypdf/_encryption.py @@ -959,7 +959,6 @@ def __init__( self.R = R self.Length = Length # key_size self.P = (P + 0x100000000) % 0x100000000 # maybe P < 0 - self.entry = entry self.EncryptMetadata = EncryptMetadata self.id1_entry = first_id_entry self.StmF = StmF diff --git a/pypdf/_writer.py b/pypdf/_writer.py index 2f9754dee..193ce7812 100644 --- a/pypdf/_writer.py +++ b/pypdf/_writer.py @@ -1221,6 +1221,7 @@ def encrypt( if owner_password is None: owner_password = user_password + if algorithm is not None: try: alg = getattr(EncryptAlgorithm, algorithm.replace("-", "_")) @@ -1296,8 +1297,6 @@ def _write_pdf_structure(self, stream: StreamType) -> List[int]: stream.write(b"%\xE2\xE3\xCF\xD3\n") for i, obj in enumerate(self._objects): - obj = self._objects[i] - # If the obj is None we can't write anything if obj is not None: idnum = i + 1 object_positions.append(stream.tell()) diff --git a/pypdf/generic/_base.py b/pypdf/generic/_base.py index 303726dd2..5d1dfaf29 100644 --- a/pypdf/generic/_base.py +++ b/pypdf/generic/_base.py @@ -37,6 +37,7 @@ from .._utils import ( StreamType, b_, + deprecate_no_replacement, deprecation_with_replacement, logger_warning, read_non_whitespace, @@ -93,7 +94,9 @@ def clone( Returns: The cloned PdfObject """ - raise Exception("clone PdfObject") + raise NotImplementedError( + f"{self.__class__.__name__} does not implement .clone so far" + ) def _reference_clone( self, clone: Any, pdf_dest: PdfWriterProtocol, force_duplicate: bool = False @@ -168,6 +171,10 @@ def clone( def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(b"null") @staticmethod @@ -181,7 +188,7 @@ def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) def __repr__(self) -> str: return "NullObject" @@ -222,6 +229,10 @@ def __repr__(self) -> str: def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) if self.value: stream.write(b"true") else: @@ -231,7 +242,7 @@ def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) @staticmethod def read_from_stream(stream: StreamType) -> "BooleanObject": @@ -315,13 +326,17 @@ def __ne__(self, other: Any) -> bool: def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(b_(f"{self.idnum} {self.generation} R")) def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) @staticmethod def read_from_stream(stream: StreamType, pdf: Any) -> "IndirectObject": # PdfReader @@ -401,13 +416,17 @@ def as_numeric(self) -> float: def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(self.myrepr().encode("utf8")) def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) class NumberObject(int, PdfObject): @@ -438,13 +457,17 @@ def as_numeric(self) -> int: def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(repr(self).encode("utf8")) def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) @staticmethod def read_from_stream(stream: StreamType) -> Union["NumberObject", "FloatObject"]: @@ -492,6 +515,10 @@ def original_bytes(self) -> bytes: def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(b"<") stream.write(binascii.hexlify(self)) stream.write(b">") @@ -500,7 +527,7 @@ def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) class TextStringObject(str, PdfObject): # noqa: SLOT000 @@ -565,6 +592,10 @@ def get_encoded_bytes(self) -> bytes: def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) bytearr = self.get_encoded_bytes() stream.write(b"(") for c in bytearr: @@ -582,7 +613,7 @@ def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) class NameObject(str, PdfObject): # noqa: SLOT000 @@ -611,13 +642,17 @@ def clone( def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(self.renumber()) # b_(renumber(self))) def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) def renumber(self) -> bytes: out = self[0].encode("utf-8") diff --git a/pypdf/generic/_data_structures.py b/pypdf/generic/_data_structures.py index 18e247910..72e239ec7 100644 --- a/pypdf/generic/_data_structures.py +++ b/pypdf/generic/_data_structures.py @@ -39,6 +39,7 @@ WHITESPACES, StreamType, b_, + deprecate_no_replacement, deprecate_with_replacement, deprecation_with_replacement, logger_warning, @@ -112,17 +113,21 @@ def items(self) -> Iterable[Any]: def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(b"[") for data in self: stream.write(b" ") - data.write_to_stream(stream, encryption_key) + data.write_to_stream(stream) stream.write(b" ]") def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) @staticmethod def read_from_stream( @@ -353,11 +358,15 @@ def xmpMetadata(self) -> Optional[PdfObject]: # deprecated def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(b"<<\n") for key, value in list(self.items()): - key.write_to_stream(stream, encryption_key) + key.write_to_stream(stream) stream.write(b" ") - value.write_to_stream(stream, encryption_key) + value.write_to_stream(stream) stream.write(b"\n") stream.write(b">>") @@ -365,7 +374,7 @@ def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) @staticmethod def read_from_stream( @@ -798,8 +807,12 @@ def _data(self, value: Any) -> None: def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) self[NameObject(SA.LENGTH)] = NumberObject(len(self._data)) - DictionaryObject.write_to_stream(self, stream, encryption_key) + DictionaryObject.write_to_stream(self, stream) del self[SA.LENGTH] stream.write(b"\nstream\n") stream.write(self._data) @@ -1449,18 +1462,22 @@ def getDestArray(self) -> "ArrayObject": # deprecated def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(b"<<\n") key = NameObject("/D") - key.write_to_stream(stream, encryption_key) + key.write_to_stream(stream) stream.write(b" ") value = self.dest_array - value.write_to_stream(stream, encryption_key) + value.write_to_stream(stream) key = NameObject("/S") - key.write_to_stream(stream, encryption_key) + key.write_to_stream(stream) stream.write(b" ") value_s = NameObject("/GoTo") - value_s.write_to_stream(stream, encryption_key) + value_s.write_to_stream(stream) stream.write(b"\n") stream.write(b">>") diff --git a/pypdf/generic/_outline.py b/pypdf/generic/_outline.py index e67ce0242..515c515a3 100644 --- a/pypdf/generic/_outline.py +++ b/pypdf/generic/_outline.py @@ -1,6 +1,6 @@ from typing import Any, Union -from .._utils import StreamType, deprecation_with_replacement +from .._utils import StreamType, deprecate_no_replacement, deprecation_with_replacement from ._base import NameObject from ._data_structures import Destination @@ -9,22 +9,26 @@ class OutlineItem(Destination): def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) stream.write(b"<<\n") for key in [ NameObject(x) for x in ["/Title", "/Parent", "/First", "/Last", "/Next", "/Prev"] if x in self ]: - key.write_to_stream(stream, encryption_key) + key.write_to_stream(stream) stream.write(b" ") value = self.raw_get(key) - value.write_to_stream(stream, encryption_key) + value.write_to_stream(stream) stream.write(b"\n") key = NameObject("/Dest") - key.write_to_stream(stream, encryption_key) + key.write_to_stream(stream) stream.write(b" ") value = self.dest_array - value.write_to_stream(stream, encryption_key) + value.write_to_stream(stream) stream.write(b"\n") stream.write(b">>") diff --git a/pypdf/xmp.py b/pypdf/xmp.py index d90964113..08e060a2e 100644 --- a/pypdf/xmp.py +++ b/pypdf/xmp.py @@ -24,6 +24,7 @@ from ._utils import ( StreamType, + deprecate_no_replacement, deprecate_with_replacement, deprecation_with_replacement, ) @@ -234,7 +235,11 @@ def rdfRoot(self) -> XmlElement: # deprecated def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] = None ) -> None: - self.stream.write_to_stream(stream, encryption_key) + if encryption_key is not None: # deprecated + deprecate_no_replacement( + "the encryption_key parameter of write_to_stream", "5.0.0" + ) + self.stream.write_to_stream(stream) def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] @@ -245,7 +250,7 @@ def writeToStream( .. deprecated:: 1.28.0 """ deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") - self.write_to_stream(stream, encryption_key) + self.write_to_stream(stream) def get_element(self, about_uri: str, namespace: str, name: str) -> Iterator[Any]: for desc in self.rdf_root.getElementsByTagNameNS(RDF_NAMESPACE, "Description"): diff --git a/tests/test_generic.py b/tests/test_generic.py index b9688f558..8ee1500fe 100644 --- a/tests/test_generic.py +++ b/tests/test_generic.py @@ -250,7 +250,10 @@ def test_destination_fit_r(): def test_destination_fit_v(): - Destination(NameObject("title"), NullObject(), Fit.fit_vertically(left=0)) + d = Destination(NameObject("title"), NullObject(), Fit.fit_vertically(left=0)) + + writer = PdfWriter() + writer.add_named_destination_object(d) # Trigger Exception Destination(NameObject("title"), NullObject(), Fit.fit_vertically(left=None)) @@ -302,7 +305,7 @@ def test_read_object_comment(): def test_bytestringobject(): bo = ByteStringObject("stream", encoding="utf-8") stream = BytesIO(b"") - bo.write_to_stream(stream, encryption_key="foobar") + bo.write_to_stream(stream) stream.seek(0, 0) assert stream.read() == b"<73747265616d>" # TODO: how can we verify this? @@ -1077,7 +1080,7 @@ def test_cloning(caplog): writer = PdfWriter() with pytest.raises(Exception) as exc: PdfObject().clone(writer) - assert "clone PdfObject" in exc.value.args[0] + assert "PdfObject does not implement .clone so far" in exc.value.args[0] obj1 = DictionaryObject() obj1.indirect_reference = None @@ -1170,6 +1173,10 @@ def test_destination_withoutzoom(): reader = PdfReader(BytesIO(get_pdf_from_url(url, name=name))) reader.outline + out = BytesIO() + writer = PdfWriter(clone_from=reader) + writer.write(out) + def test_encodedstream_set_data(): """