From 24e2ac4f10cb428658a9e52019d7498400887cc4 Mon Sep 17 00:00:00 2001 From: Martin Thoma Date: Thu, 9 Jun 2022 21:28:25 +0200 Subject: [PATCH] DEP: Rename names to be PEP8-compliant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PdfWriter.get_page: the pageNumber parameter is renamed to page_number PyPDF2.generic: * readHexStringFromStream ➔ read_hex_string_from_stream * TreeObject.emptyTree ➔ TreeObject.empty_tree xmp: * XmpInformation.rdfRoot ➔ XmpInformation.rdf_root * XmpInformation.xmp_createDate ➔ XmpInformation.xmp_create_date * XmpInformation.xmp_creatorTool ➔ XmpInformation.xmp_creator_tool * XmpInformation.xmp_metadataDate ➔ XmpInformation.xmp_metadata_date * XmpInformation.xmp_modifyDate ➔ XmpInformation.xmp_modify_date * XmpInformation.xmpMetadata ➔ XmpInformation.xmp_metadata * XmpInformation.xmpmm_documentId ➔ XmpInformation.xmpmm_document_id * XmpInformation.xmpmm_instanceId ➔ XmpInformation.xmpmm_instance_id --- PyPDF2/_writer.py | 20 ++++++++-- PyPDF2/filters.py | 12 ++---- PyPDF2/generic.py | 30 ++++++++++++--- PyPDF2/xmp.py | 89 +++++++++++++++++++++++++++++++++++-------- make_changelog.py | 2 +- tests/test_generic.py | 22 +++++------ tests/test_xmp.py | 2 +- 7 files changed, 132 insertions(+), 45 deletions(-) diff --git a/PyPDF2/_writer.py b/PyPDF2/_writer.py index e38af4d741..67a6babd09 100644 --- a/PyPDF2/_writer.py +++ b/PyPDF2/_writer.py @@ -215,18 +215,30 @@ def insertPage(self, page: PageObject, index: int = 0) -> None: # pragma: no co deprecate_with_replacement("insertPage", "insert_page") self.insert_page(page, index) - def get_page(self, pageNumber: int) -> PageObject: # TODO: PEP8 + def get_page( + self, page_number: Optional[int] = None, pageNumber: Optional[int] = None + ) -> PageObject: """ Retrieve a page by number from this PDF file. - :param int pageNumber: The page number to retrieve + :param int page_number: The page number to retrieve (pages begin at zero) - :return: the page at the index given by *pageNumber* + :return: the page at the index given by *page_number* :rtype: :class:`PageObject` """ + if pageNumber is not None: + if page_number is not None: + raise ValueError("Please only use the page_number parameter") + else: + deprecate_with_replacement( + "get_page(pageNumber)", "get_page(page_number)", "4.0.0" + ) + page_number = pageNumber + if page_number is None and pageNumber is None: + raise ValueError("Please specify the page_number") pages = cast(Dict[str, Any], self.get_object(self._pages)) # XXX: crude hack - return pages[PA.KIDS][pageNumber].get_object() + return pages[PA.KIDS][page_number].get_object() def getPage(self, pageNumber: int) -> PageObject: # pragma: no cover """ diff --git a/PyPDF2/filters.py b/PyPDF2/filters.py index ca21f4aec9..875aba180f 100644 --- a/PyPDF2/filters.py +++ b/PyPDF2/filters.py @@ -76,9 +76,8 @@ def compress(data: bytes) -> bytes: class FlateDecode: @staticmethod def decode( - # TODO: PEP8 data: bytes, - decodeParms: Union[None, ArrayObject, DictionaryObject], + decodeParms: Union[None, ArrayObject, DictionaryObject], # TODO: PEP8 ) -> bytes: """ :param data: flate-encoded data. @@ -171,9 +170,8 @@ class ASCIIHexDecode: @staticmethod def decode( - # TODO: PEP8 data: str, - decodeParms: Union[None, ArrayObject, DictionaryObject] = None, + decodeParms: Union[None, ArrayObject, DictionaryObject] = None, # TODO: PEP8 ) -> str: """ :param data: a str sequence of hexadecimal-encoded values to be @@ -289,9 +287,8 @@ def decode(self) -> str: @staticmethod def decode( - # TODO: PEP8 data: bytes, - decodeParms: Union[None, ArrayObject, DictionaryObject] = None, + decodeParms: Union[None, ArrayObject, DictionaryObject] = None, # TODO: PEP8 ) -> str: """ :param data: ``bytes`` or ``str`` text to decode. @@ -404,8 +401,7 @@ def _get_parameters( @staticmethod def decode( data: bytes, - # TODO: PEP8 - decodeParms: Union[None, ArrayObject, DictionaryObject] = None, + decodeParms: Union[None, ArrayObject, DictionaryObject] = None, # TODO: PEP8 height: int = 0, ) -> bytes: parms = CCITTFaxDecode._get_parameters(decodeParms, height) diff --git a/PyPDF2/generic.py b/PyPDF2/generic.py index f16de8db62..933e2a90af 100644 --- a/PyPDF2/generic.py +++ b/PyPDF2/generic.py @@ -357,7 +357,16 @@ def readFromStream( return NumberObject.read_from_stream(stream) -def readHexStringFromStream( # TODO: PEP8 +def readHexStringFromStream( + stream: StreamType, +) -> Union["TextStringObject", "ByteStringObject"]: + deprecate_with_replacement( + "readHexStringFromStream", "read_hex_string_from_stream", "4.0.0" + ) + return read_hex_string_from_stream(stream) + + +def read_hex_string_from_stream( stream: StreamType, ) -> Union["TextStringObject", "ByteStringObject"]: stream.read(1) @@ -380,7 +389,15 @@ def readHexStringFromStream( # TODO: PEP8 return createStringObject(b_(txt)) -def readStringFromStream( # TODO: PEP8 +def readStringFromStream( + stream: StreamType, + forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, +) -> Union["TextStringObject", "ByteStringObject"]: + deprecate_with_replacement("readStringFromStream", "read_string_from_stream") + return read_string_from_stream(stream, forced_encoding) + + +def read_string_from_stream( stream: StreamType, forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, ) -> Union["TextStringObject", "ByteStringObject"]: @@ -941,7 +958,10 @@ def remove_child(self, child: Any) -> None: del child_obj[NameObject("/Prev")] def emptyTree(self) -> None: - # TODO: Missing rename + deprecate_with_replacement("emptyTree", "empty_tree", "4.0.0") + self.empty_tree() + + def empty_tree(self) -> None: for child in self: child_obj = child.get_object() del child_obj[NameObject("/Parent")] @@ -1251,13 +1271,13 @@ def read_object( if peek == b_("<<"): return DictionaryObject.read_from_stream(stream, pdf, forced_encoding) else: - return readHexStringFromStream(stream) + return read_hex_string_from_stream(stream) elif idx == 2: return ArrayObject.read_from_stream(stream, pdf, forced_encoding) elif idx == 3 or idx == 4: return BooleanObject.read_from_stream(stream) elif idx == 5: - return readStringFromStream(stream, forced_encoding) + return read_string_from_stream(stream, forced_encoding) elif idx == 6: return NullObject.read_from_stream(stream) elif idx == 7: diff --git a/PyPDF2/xmp.py b/PyPDF2/xmp.py index ea93d68948..ee129f3227 100644 --- a/PyPDF2/xmp.py +++ b/PyPDF2/xmp.py @@ -204,11 +204,16 @@ class XmpInformation(PdfObject): def __init__(self, stream: ContentStream) -> None: self.stream = stream doc_root: Document = parseString(self.stream.get_data()) - self.rdfRoot: XmlElement = doc_root.getElementsByTagNameNS( # TODO: PEP8 + self.rdf_root: XmlElement = doc_root.getElementsByTagNameNS( RDF_NAMESPACE, "RDF" )[0] self.cache: Dict[Any, Any] = {} + @property + def rdfRoot(self) -> XmlElement: + deprecate_with_replacement("rdfRoot", "rdf_root", "4.0.0") + return self.rdf_root + def write_to_stream( self, stream: StreamType, encryption_key: Union[None, str, bytes] ) -> None: @@ -226,7 +231,7 @@ def writeToStream( self.write_to_stream(stream, encryption_key) def get_element(self, about_uri: str, namespace: str, name: str) -> Iterator[Any]: - for desc in self.rdfRoot.getElementsByTagNameNS(RDF_NAMESPACE, "Description"): + for desc in self.rdf_root.getElementsByTagNameNS(RDF_NAMESPACE, "Description"): if desc.getAttributeNS(RDF_NAMESPACE, "about") == about_uri: attr = desc.getAttributeNodeNS(namespace, name) if attr is not None: @@ -245,7 +250,7 @@ def getElement( return self.get_element(aboutUri, namespace, name) def get_nodes_in_namespace(self, about_uri: str, namespace: str) -> Iterator[Any]: - for desc in self.rdfRoot.getElementsByTagNameNS(RDF_NAMESPACE, "Description"): + for desc in self.rdf_root.getElementsByTagNameNS(RDF_NAMESPACE, "Description"): if desc.getAttributeNS(RDF_NAMESPACE, "about") == about_uri: for i in range(desc.attributes.length): attr = desc.attributes.item(i) @@ -370,8 +375,7 @@ def _get_text(self, element: XmlElement) -> str: The name of the tool that created the PDF document. """ - # TODO: PEP8 - xmp_createDate = property( + xmp_create_date = property( _getter_single(XMP_NAMESPACE, "CreateDate", _converter_date) ) """ @@ -379,8 +383,17 @@ def _get_text(self, element: XmlElement) -> str: time are returned as a UTC datetime.datetime object. """ - # TODO: PEP8 - xmp_modifyDate = property( + @property + def xmp_createDate(self) -> datetime.datetime: + deprecate_with_replacement("xmp_createDate", "xmp_create_date") + return self.xmp_create_date + + @xmp_createDate.setter + def xmp_createDate(self, value: datetime.datetime): + deprecate_with_replacement("xmp_createDate", "xmp_create_date") + self.xmp_create_date = value + + xmp_modify_date = property( _getter_single(XMP_NAMESPACE, "ModifyDate", _converter_date) ) """ @@ -388,8 +401,17 @@ def _get_text(self, element: XmlElement) -> str: are returned as a UTC datetime.datetime object. """ - # TODO: PEP8 - xmp_metadataDate = property( + @property + def xmp_modifyDate(self) -> datetime.datetime: + deprecate_with_replacement("xmp_modifyDate", "xmp_modify_date") + return self.xmp_modify_date + + @xmp_modifyDate.setter + def xmp_modifyDate(self, value: datetime.datetime): + deprecate_with_replacement("xmp_modifyDate", "xmp_modify_date") + self.xmp_modify_date = value + + xmp_metadata_date = property( _getter_single(XMP_NAMESPACE, "MetadataDate", _converter_date) ) """ @@ -398,25 +420,62 @@ def _get_text(self, element: XmlElement) -> str: object. """ - # TODO: PEP8 - xmp_creatorTool = property(_getter_single(XMP_NAMESPACE, "CreatorTool")) + @property + def xmp_metadataDate(self) -> datetime.datetime: + deprecate_with_replacement("xmp_metadataDate", "xmp_metadata_date") + return self.xmp_metadata_date + + @xmp_metadataDate.setter + def xmp_metadataDate(self, value: datetime.datetime): + deprecate_with_replacement("xmp_metadataDate", "xmp_metadata_date") + self.xmp_metadata_date = value + + xmp_creator_tool = property(_getter_single(XMP_NAMESPACE, "CreatorTool")) """ The name of the first known tool used to create the resource. """ - # TODO: PEP8 - xmpmm_documentId = property(_getter_single(XMPMM_NAMESPACE, "DocumentID")) + @property + def xmp_creatorTool(self) -> str: + deprecate_with_replacement("xmp_creatorTool", "xmp_creator_tool") + return self.xmp_creator_tool + + @xmp_creatorTool.setter + def xmp_creatorTool(self, value: str): + deprecate_with_replacement("xmp_creatorTool", "xmp_creator_tool") + self.xmp_creator_tool = value + + xmpmm_document_id = property(_getter_single(XMPMM_NAMESPACE, "DocumentID")) """ The common identifier for all versions and renditions of this resource. """ - # TODO: PEP8 - xmpmm_instanceId = property(_getter_single(XMPMM_NAMESPACE, "InstanceID")) + @property + def xmpmm_documentId(self) -> str: + deprecate_with_replacement("xmpmm_documentId", "xmpmm_document_id") + return self.xmpmm_document_id + + @xmpmm_documentId.setter + def xmpmm_documentId(self, value: str): + deprecate_with_replacement("xmpmm_documentId", "xmpmm_document_id") + self.xmpmm_document_id = value + + xmpmm_instance_id = property(_getter_single(XMPMM_NAMESPACE, "InstanceID")) """ An identifier for a specific incarnation of a document, updated each time a file is saved. """ + @property + def xmpmm_instanceId(self) -> str: + deprecate_with_replacement("xmpmm_instanceId", "xmpmm_instance_id") + return self.xmpmm_instance_id + + @xmpmm_instanceId.setter + def xmpmm_instanceId(self, value: str): + deprecate_with_replacement("xmpmm_instanceId", "xmpmm_instance_id") + self.xmpmm_instance_id = value + @property def custom_properties(self) -> Dict[Any, Any]: """ diff --git a/make_changelog.py b/make_changelog.py index 32b36e84ca..75e4278bde 100644 --- a/make_changelog.py +++ b/make_changelog.py @@ -20,7 +20,7 @@ def main(changelog_path: str): changes = get_formatted_changes(git_tag) print("-" * 80) print(changes) - # TODO: Write changes to changelog + new_version = version_bump(git_tag) today = datetime.now() header = f"Version {new_version}, {today:%Y-%m-%d}\n" diff --git a/tests/test_generic.py b/tests/test_generic.py index 2bb36bb4b7..c7666c3f10 100644 --- a/tests/test_generic.py +++ b/tests/test_generic.py @@ -23,9 +23,9 @@ TreeObject, createStringObject, encode_pdfdocencoding, + read_hex_string_from_stream, read_object, - readHexStringFromStream, - readStringFromStream, + read_string_from_stream, ) TESTS_ROOT = os.path.abspath(os.path.dirname(__file__)) @@ -115,43 +115,43 @@ def test_indirect_object_premature(value): def test_readHexStringFromStream(): stream = BytesIO(b"a1>") - assert readHexStringFromStream(stream) == "\x10" + assert read_hex_string_from_stream(stream) == "\x10" def test_readHexStringFromStream_exception(): stream = BytesIO(b"") with pytest.raises(PdfStreamError) as exc: - readHexStringFromStream(stream) + read_hex_string_from_stream(stream) assert exc.value.args[0] == "Stream has ended unexpectedly" def test_readStringFromStream_exception(): stream = BytesIO(b"x") with pytest.raises(PdfStreamError) as exc: - readStringFromStream(stream) + read_string_from_stream(stream) assert exc.value.args[0] == "Stream has ended unexpectedly" def test_readStringFromStream_not_in_escapedict_no_digit(): stream = BytesIO(b"x\\y") with pytest.raises(PdfReadError) as exc: - readStringFromStream(stream) + read_string_from_stream(stream) assert exc.value.args[0] == "Stream has ended unexpectedly" def test_readStringFromStream_multichar_eol(): stream = BytesIO(b"x\\\n )") - assert readStringFromStream(stream) == " " + assert read_string_from_stream(stream) == " " def test_readStringFromStream_multichar_eol2(): stream = BytesIO(b"x\\\n\n)") - assert readStringFromStream(stream) == "" + assert read_string_from_stream(stream) == "" def test_readStringFromStream_excape_digit(): stream = BytesIO(b"x\\1a )") - assert readStringFromStream(stream) == "\x01 " + assert read_string_from_stream(stream) == "\x01 " def test_NameObject(): @@ -179,7 +179,7 @@ def test_destination_fit_r(): assert d.top == FloatObject(0) assert d.bottom == FloatObject(0) assert list(d) == [] - d.emptyTree() + d.empty_tree() def test_destination_fit_v(): @@ -401,4 +401,4 @@ def test_remove_child_in_tree(): tree.add_child(obj, writer) tree.remove_child(obj) tree.add_child(obj, writer) - tree.emptyTree() + tree.empty_tree() diff --git a/tests/test_xmp.py b/tests/test_xmp.py index 665c41137b..0d37ac6496 100644 --- a/tests/test_xmp.py +++ b/tests/test_xmp.py @@ -72,7 +72,7 @@ def test_regression_issue774(): def test_regression_issue914(): path = os.path.join(RESOURCE_ROOT, "issue-914-xmp-data.pdf") reader = PdfReader(path) - assert reader.xmp_metadata.xmp_modifyDate == datetime(2022, 4, 9, 15, 22, 43) + assert reader.xmp_metadata.xmp_modify_date == datetime(2022, 4, 9, 15, 22, 43) @pytest.mark.parametrize(