From 2c1277cf6e7d800758ed4da341bbbda561b9065d Mon Sep 17 00:00:00 2001 From: Martin Thoma Date: Fri, 6 Jan 2023 12:31:42 +0100 Subject: [PATCH] DOC: Use google style docstrings The Google Docstring style is way more readable than ReST style docstrings. Additionally, replace most instances of 'pragma: no-cover' by 'deprecated'. Tools used: - pyment - pydocstyle --- docs/conf.py | 11 +- make_changelog.py | 7 + mutmut_config.py | 1 + pypdf/_encryption.py | 163 ++++++++++++- pypdf/_merger.py | 111 +++++---- pypdf/_page.py | 68 +++--- pypdf/_page_labels.py | 11 +- pypdf/_protocols.py | 4 +- pypdf/_reader.py | 178 +++++++++----- pypdf/_security.py | 66 ++++- pypdf/_utils.py | 53 ++++- pypdf/_writer.py | 383 +++++++++++++++++------------- pypdf/constants.py | 4 +- pypdf/filters.py | 63 +++-- pypdf/generic/__init__.py | 6 +- pypdf/generic/_annotations.py | 79 +++--- pypdf/generic/_base.py | 43 ++-- pypdf/generic/_data_structures.py | 128 +++++++--- pypdf/generic/_fit.py | 35 +++ pypdf/generic/_outline.py | 2 +- pypdf/generic/_rectangle.py | 54 ++--- pypdf/generic/_utils.py | 11 +- pypdf/pagerange.py | 31 ++- pypdf/xmp.py | 39 +-- 24 files changed, 1071 insertions(+), 480 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ba0cb0c58..969463dff 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,9 +1,10 @@ -# Configuration file for the Sphinx documentation builder. -# -# This file only contains a selection of the most common options. For a full -# list see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html +""" +Configuration file for the Sphinx documentation builder. +This file only contains a selection of the most common options. For a full +list see the documentation: +https://www.sphinx-doc.org/en/master/usage/configuration.html +""" # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, diff --git a/make_changelog.py b/make_changelog.py index d12edf0fe..d5f0b9379 100644 --- a/make_changelog.py +++ b/make_changelog.py @@ -38,23 +38,27 @@ def main(changelog_path: str): def version_bump(git_tag: str) -> str: + """Increase the patch version of the git tag by one.""" # just assume a patch version change major, minor, patch = git_tag.split(".") return f"{major}.{minor}.{int(patch) + 1}" def get_changelog(changelog_path: str) -> str: + """Read the changelog.""" with open(changelog_path) as fh: changelog = fh.read() return changelog def write_changelog(new_changelog: str, changelog_path: str) -> None: + """Write the changelog.""" with open(changelog_path, "w") as fh: fh.write(new_changelog) def get_formatted_changes(git_tag: str) -> str: + """Format the changes done since the last tag.""" commits = get_git_commits_since_tag(git_tag) # Group by prefix @@ -100,6 +104,7 @@ def get_formatted_changes(git_tag: str) -> str: def get_most_recent_git_tag(): + """Get the git tag most recently created.""" git_tag = str( subprocess.check_output( ["git", "describe", "--abbrev=0"], stderr=subprocess.STDOUT @@ -109,6 +114,7 @@ def get_most_recent_git_tag(): def get_git_commits_since_tag(git_tag) -> List[Change]: + """Get all commits since the last tag.""" commits = str( subprocess.check_output( [ @@ -125,6 +131,7 @@ def get_git_commits_since_tag(git_tag) -> List[Change]: def parse_commit_line(line) -> Change: + """Parse the first line of a git commit message.""" if "\\t" not in line: raise ValueError(f"Invalid commit line: {line}") commit_hash, rest = line.split("\\t", 1) diff --git a/mutmut_config.py b/mutmut_config.py index 865c4d805..1c6e7c039 100644 --- a/mutmut_config.py +++ b/mutmut_config.py @@ -6,6 +6,7 @@ def pre_mutation(context): + """Filter what to mutate.""" line = context.current_source_line.strip() if ( "_codecs" in context.filename diff --git a/pypdf/_encryption.py b/pypdf/_encryption.py index 5c80e6003..038067a4b 100644 --- a/pypdf/_encryption.py +++ b/pypdf/_encryption.py @@ -288,6 +288,22 @@ def compute_key( for security handlers of revision 2 but, for security handlers of revision 3 or greater, shall depend on the value of the encryption dictionary’s Length entry. + + Args: + password: The encryption secret as a bytes-string + rev: The encryption revision (see PDF standard) + key_size: The size of the key in bytes + o_entry: The owner entry + P: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, all other + bits are ignored and all operations are permitted. If bit 2 is set to 0, + permission for operations are based on the values of the remaining flags + defined in Table 24. + id1_entry: + metadata_encrypted: A boolean indicating if the metadata is encrypted. + + Returns: + The u_hash digest of length key_size """ a = _padding(password) u_hash = hashlib.md5(a) @@ -335,6 +351,14 @@ def compute_O_value_key(owner_password: bytes, rev: int, key_size: int) -> bytes of the iteration counter (from 1 to 19). h) Store the output from the final invocation of the RC4 function as the value of the O entry in the encryption dictionary. + + Args: + owner_password: + rev: The encryption revision (see PDF standard) + key_size: The size of the key in bytes + + Returns: + The RC4 key """ a = _padding(owner_password) o_hash_digest = hashlib.md5(a).digest() @@ -348,7 +372,17 @@ def compute_O_value_key(owner_password: bytes, rev: int, key_size: int) -> bytes @staticmethod def compute_O_value(rc4_key: bytes, user_password: bytes, rev: int) -> bytes: - """See :func:`compute_O_value_key`.""" + """ + See :func:`compute_O_value_key`. + + Args: + rc4_key: + user_password: + rev: The encryption revision (see PDF standard) + + Returns: + The RC4 encrypted + """ a = _padding(user_password) rc4_enc = RC4_encrypt(rc4_key, a) if rev >= 3: @@ -371,6 +405,14 @@ def compute_U_value(key: bytes, rev: int, id1_entry: bytes) -> bytes: function with the encryption key from the preceding step. c) Store the result of step (b) as the value of the U entry in the encryption dictionary. + + Args: + key: + rev: The encryption revision (see PDF standard) + id1_entry: + + Returns: + The value """ if rev <= 2: value = RC4_encrypt(key, _PADDING) @@ -432,6 +474,23 @@ def verify_user_password( dictionary’s U (user password) value (Security handlers of revision 2)" or "Algorithm 5: Computing the encryption dictionary’s U (user password) value (Security handlers of revision 3 or greater)") shall be used to decrypt the document. + + Args: + user_password: The user passwort as a bytes stream + rev: The encryption revision (see PDF standard) + key_size: The size of the key in bytes + o_entry: The owner entry + u_entry: The user entry + P: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, all other + bits are ignored and all operations are permitted. If bit 2 is set to 0, + permission for operations are based on the values of the remaining flags + defined in Table 24. + id1_entry: + metadata_encrypted: A boolean indicating if the metadata is encrypted. + + Returns: + The key """ key = AlgV4.compute_key( user_password, rev, key_size, o_entry, P, id1_entry, metadata_encrypted @@ -469,6 +528,23 @@ def verify_owner_password( between each byte of the key and the single-byte value of the iteration counter (from 19 to 0). c) The result of step (b) purports to be the user password. Authenticate this user password using "Algorithm 6: Authenticating the user password". If it is correct, the password supplied is the correct owner password. + + Args: + owner_password: + rev: The encryption revision (see PDF standard) + key_size: The size of the key in bytes + o_entry: The owner entry + u_entry: The user entry + P: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, all other + bits are ignored and all operations are permitted. If bit 2 is set to 0, + permission for operations are based on the values of the remaining flags + defined in Table 24. + id1_entry: + metadata_encrypted: A boolean indicating if the metadata is encrypted. + + Returns: + bytes """ rc4_key = AlgV4.compute_O_value_key(owner_password, rev, key_size) @@ -524,6 +600,21 @@ def verify_owner_password( the file encryption key as the key. Verify that bytes 9-11 of the result are the characters ‘a’, ‘d’, ‘b’. Bytes 0-3 of the decrypted Perms entry, treated as a little-endian integer, are the user permissions. They should match the value in the P key. + + Args: + R: A number specifying which revision of the standard security + handler shall be used to interpret this dictionary + password: The owner password + o_value: A 32-byte string, based on both the owner and user passwords, + that shall be used in computing the encryption key and in determining + whether a valid owner password was entered + oe_value: + u_value: A 32-byte string, based on the user password, that shall be + used in determining whether to prompt the user for a password and, if so, + whether a valid user or owner password was entered. + + Returns: + The key """ password = password[:127] if ( @@ -540,7 +631,21 @@ def verify_owner_password( def verify_user_password( R: int, password: bytes, u_value: bytes, ue_value: bytes ) -> bytes: - """See :func:`verify_owner_password`.""" + """ + See :func:`verify_owner_password`. + + Args: + R: A number specifying which revision of the standard security + handler shall be used to interpret this dictionary + password: The user password + u_value: A 32-byte string, based on the user password, that shall be + used in determining whether to prompt the user for a password and, if so, + whether a valid user or owner password was entered. + ue_value: + + Returns: + bytes + """ password = password[:127] if AlgV5.calculate_hash(R, password, u_value[32:40], b"") != u_value[:32]: return b"" @@ -573,7 +678,22 @@ def calculate_hash(R: int, password: bytes, salt: bytes, udata: bytes) -> bytes: def verify_perms( key: bytes, perms: bytes, p: int, metadata_encrypted: bool ) -> bool: - """See :func:`verify_owner_password` and :func:`compute_Perms_value`.""" + """ + See :func:`verify_owner_password` and :func:`compute_perms_value`. + + Args: + key: The owner password + perms: + p: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, all other + bits are ignored and all operations are permitted. If bit 2 is set to 0, + permission for operations are based on the values of the remaining flags + defined in Table 24. + metadata_encrypted: + + Returns: + A boolean + """ b8 = b"T" if metadata_encrypted else b"F" p1 = struct.pack(" Tuple[bytes, bytes]: 2. Compute the 32-byte SHA-256 hash of the password concatenated with the User Key Salt. Using this hash as the key, encrypt the file encryption key using AES-256 in CBC mode with no padding and an initialization vector of zero. The resulting 32-byte string is stored as the UE key. + + Args: + password: + key: + + Returns: + A tuple (u-value, ue value) """ random_bytes = bytes(random.randrange(0, 256) for _ in range(16)) val_salt = random_bytes[:8] @@ -637,6 +764,16 @@ def compute_O_value( concatenated with the 48-byte U string as generated in Algorithm 3.8. Using this hash as the key, encrypt the file encryption key using AES-256 in CBC mode with no padding and an initialization vector of zero. The resulting 32-byte string is stored as the OE key. + + Args: + password: + key: + u_value: A 32-byte string, based on the user password, that shall be + used in determining whether to prompt the user for a password and, if so, + whether a valid user or owner password was entered. + + Returns: + A tuple (O value, OE value) """ random_bytes = bytes(random.randrange(0, 256) for _ in range(16)) val_salt = random_bytes[:8] @@ -664,6 +801,18 @@ def compute_Perms_value(key: bytes, p: int, metadata_encrypted: bool) -> bytes: 6. Encrypt the 16-byte block using AES-256 in ECB mode with an initialization vector of zero, using the file encryption key as the key. The result (16 bytes) is stored as the Perms string, and checked for validity when the file is opened. + + Args: + key: + p: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, all other + bits are ignored and all operations are permitted. If bit 2 is set to 0, + permission for operations are based on the values of the remaining flags + defined in Table 24. + metadata_encrypted: A boolean indicating if the metadata is encrypted. + + Returns: + The perms value """ b8 = b"T" if metadata_encrypted else b"F" rr = bytes(random.randrange(0, 256) for _ in range(4)) @@ -736,6 +885,14 @@ def decrypt_object(self, obj: PdfObject, idnum: int, generation: int) -> PdfObje block size parameter is set to 16 bytes, and the initialization vector is a 16-byte random number that is stored as the first 16 bytes of the encrypted stream or string. The output is the encrypted data to be stored in the PDF file. + + Args: + obj: + idnum: + generation: + + Returns: + The PdfObject """ pack1 = struct.pack("` (or :meth:`append()`) and :meth:`write()` for usage information. - :param bool strict: Determines whether user should be warned of all - problems and also causes some correctable problems to be fatal. - Defaults to ``False``. - :param fileobj: Output file. Can be a filename or any kind of - file-like object. + Args: + strict: Determines whether user should be warned of all + problems and also causes some correctable problems to be fatal. + Defaults to ``False``. + fileobj: Output file. Can be a filename or any kind of + file-like object. """ @deprecation_bookmark(bookmarks="outline") @@ -144,24 +145,21 @@ def merge( Merge the pages from the given file into the output file at the specified page number. - :param int page_number: The *page number* to insert this file. File will + Args: + page_number: The *page number* to insert this file. File will be inserted after the given number. - - :param fileobj: A File Object or an object that supports the standard + fileobj: A File Object or an object that supports the standard read and seek methods similar to a File Object. Could also be a string representing a path to a PDF file. - - :param str outline_item: Optionally, you may specify an outline item + outline_item: Optionally, you may specify an outline item (previously referred to as a 'bookmark') to be applied at the beginning of the included file by supplying the text of the outline item. - - :param pages: can be a :class:`PageRange` + pages: can be a :class:`PageRange` or a ``(start, stop[, step])`` tuple to merge only the specified range of pages from the source document into the output document. Can also be a list of pages to merge. - - :param bool import_outline: You may prevent the source document's + import_outline: You may prevent the source document's outline (collection of outline items, previously referred to as 'bookmarks') from being imported by specifying this as ``False``. """ @@ -298,21 +296,19 @@ def append( concatenate all pages onto the end of the file instead of specifying a position. - :param fileobj: A File Object or an object that supports the standard + Args: + fileobj: A File Object or an object that supports the standard read and seek methods similar to a File Object. Could also be a string representing a path to a PDF file. - - :param str outline_item: Optionally, you may specify an outline item + outline_item: Optionally, you may specify an outline item (previously referred to as a 'bookmark') to be applied at the beginning of the included file by supplying the text of the outline item. - - :param pages: can be a :class:`PageRange` + pages: can be a :class:`PageRange` or a ``(start, stop[, step])`` tuple to merge only the specified range of pages from the source document into the output document. Can also be a list of pages to append. - - :param bool import_outline: You may prevent the source document's + import_outline: You may prevent the source document's outline (collection of outline items, previously referred to as 'bookmarks') from being imported by specifying this as ``False``. """ @@ -322,7 +318,8 @@ def write(self, fileobj: Union[Path, StrByteType]) -> None: """ Write all data that has been merged to the given output file. - :param fileobj: Output file. Can be a filename or any kind of + Args: + fileobj: Output file. Can be a filename or any kind of file-like object. """ if self.output is None: @@ -363,15 +360,16 @@ def add_metadata(self, infos: Dict[str, Any]) -> None: """ Add custom metadata to the output. - :param dict infos: a Python dictionary where each key is a field + Args: + infos: a Python dictionary where each key is a field and each value is your new metadata. - Example: ``{u'/Title': u'My title'}`` + An example is ``{'/Title': 'My title'}`` """ if self.output is None: raise RuntimeError(ERR_CLOSED_WRITER) self.output.add_metadata(infos) - def addMetadata(self, infos: Dict[str, Any]) -> None: # pragma: no cover + def addMetadata(self, infos: Dict[str, Any]) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -380,7 +378,7 @@ def addMetadata(self, infos: Dict[str, Any]) -> None: # pragma: no cover deprecation_with_replacement("addMetadata", "add_metadata") self.add_metadata(infos) - def setPageLayout(self, layout: LayoutType) -> None: # pragma: no cover + def setPageLayout(self, layout: LayoutType) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -393,7 +391,8 @@ def set_page_layout(self, layout: LayoutType) -> None: """ Set the page layout. - :param str layout: The page layout to be used + Args: + layout: The page layout to be used .. list-table:: Valid ``layout`` arguments :widths: 50 200 @@ -417,7 +416,7 @@ def set_page_layout(self, layout: LayoutType) -> None: raise RuntimeError(ERR_CLOSED_WRITER) self.output._set_page_layout(layout) - def setPageMode(self, mode: PagemodeType) -> None: # pragma: no cover + def setPageMode(self, mode: PagemodeType) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -430,7 +429,8 @@ def set_page_mode(self, mode: PagemodeType) -> None: """ Set the page mode. - :param str mode: The page mode to use. + Args: + mode: The page mode to use. .. list-table:: Valid ``mode`` arguments :widths: 50 200 @@ -458,7 +458,14 @@ def _trim_dests( dests: Dict[str, Dict[str, Any]], pages: Union[Tuple[int, int], Tuple[int, int, int], List[int]], ) -> List[Dict[str, Any]]: - """Remove named destinations that are not a part of the specified page set.""" + """ + Remove named destinations that are not a part of the specified page set. + + Args: + pdf: + dests: + pages: + """ new_dests = [] lst = pages if isinstance(pages, list) else list(range(*pages)) for key, obj in dests.items(): @@ -476,7 +483,17 @@ def _trim_outline( outline: OutlineType, pages: Union[Tuple[int, int], Tuple[int, int, int], List[int]], ) -> OutlineType: - """Remove outline item entries that are not a part of the specified page set.""" + """ + Remove outline item entries that are not a part of the specified page set. + + Args: + pdf: + outline: + pages: + + Returns: + An outline type + """ new_outline = [] prev_header_added = True lst = pages if isinstance(pages, list) else list(range(*pages)) @@ -651,7 +668,7 @@ def find_bookmark( self, outline_item: Dict[str, Any], root: Optional[OutlineType] = None, - ) -> Optional[List[int]]: # pragma: no cover + ) -> Optional[List[int]]: # deprecated """ .. deprecated:: 2.9.0 Use :meth:`find_outline_item` instead. @@ -672,15 +689,16 @@ def add_outline_item( """ Add an outline item (commonly referred to as a "Bookmark") to this PDF file. - :param str title: Title to use for this outline item. - :param int page_number: Page number this outline item will point to. - :param parent: A reference to a parent outline item to create nested + Args: + title: Title to use for this outline item. + page_number: Page number this outline item will point to. + parent: A reference to a parent outline item to create nested outline items. - :param tuple color: Color of the outline item's font as a red, green, blue tuple + color: Color of the outline item's font as a red, green, blue tuple from 0.0 to 1.0 - :param bool bold: Outline item font is bold - :param bool italic: Outline item font is italic - :param Fit fit: The fit of the destination page. + bold: Outline item font is bold + italic: Outline item font is italic + fit: The fit of the destination page. """ if page_number is not None and pagenum is not None: raise ValueError( @@ -723,7 +741,7 @@ def addBookmark( italic: bool = False, fit: FitType = "/Fit", *args: ZoomArgType, - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 1.28.0 Use :meth:`add_outline_item` instead. @@ -749,7 +767,7 @@ def add_bookmark( italic: bool = False, fit: FitType = "/Fit", *args: ZoomArgType, - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 2.9.0 Use :meth:`add_outline_item` instead. @@ -765,7 +783,7 @@ def add_bookmark( Fit(fit_type=fit, fit_args=args), ) - def addNamedDestination(self, title: str, pagenum: int) -> None: # pragma: no cover + def addNamedDestination(self, title: str, pagenum: int) -> None: # deprecated """ .. deprecated:: 1.28.0 Use :meth:`add_named_destination` instead. @@ -784,8 +802,11 @@ def add_named_destination( """ Add a destination to the output. - :param str title: Title to use - :param int page_number: Page number this destination points at. + Args: + title: Title to use + page_number: Page number this destination points at. + title: + pagenum: """ if page_number is not None and pagenum is not None: raise ValueError( @@ -812,7 +833,7 @@ def add_named_destination( self.named_dests.append(dest) -class PdfFileMerger(PdfMerger): # pragma: no cover +class PdfFileMerger(PdfMerger): # deprecated def __init__(self, *args: Any, **kwargs: Any) -> None: deprecation_with_replacement("PdfFileMerger", "PdfMerger", "3.0.0") diff --git a/pypdf/_page.py b/pypdf/_page.py index f9ed8f592..f42da79ef 100644 --- a/pypdf/_page.py +++ b/pypdf/_page.py @@ -141,7 +141,7 @@ def _get_rectangle(self: Any, name: str, defaults: Iterable[str]) -> RectangleOb def getRectangle( self: Any, name: str, defaults: Iterable[str] -) -> RectangleObject: # pragma: no cover +) -> RectangleObject: # deprecated deprecation_no_replacement("getRectangle", "3.0.0") return _get_rectangle(self, name, defaults) @@ -153,7 +153,7 @@ def _set_rectangle(self: Any, name: str, value: Union[RectangleObject, float]) - def setRectangle( self: Any, name: str, value: Union[RectangleObject, float] -) -> None: # pragma: no cover +) -> None: # deprecated deprecation_no_replacement("setRectangle", "3.0.0") _set_rectangle(self, name, value) @@ -162,7 +162,7 @@ def _delete_rectangle(self: Any, name: str) -> None: del self[name] -def deleteRectangle(self: Any, name: str) -> None: # pragma: no cover +def deleteRectangle(self: Any, name: str) -> None: # deprecated deprecation_no_replacement("deleteRectangle", "3.0.0") del self[name] @@ -177,7 +177,7 @@ def _create_rectangle_accessor(name: str, fallback: Iterable[str]) -> property: def createRectangleAccessor( name: str, fallback: Iterable[str] -) -> property: # pragma: no cover +) -> property: # deprecated deprecation_no_replacement("createRectangleAccessor", "3.0.0") return _create_rectangle_accessor(name, fallback) @@ -452,7 +452,7 @@ def createBlankPage( pdf: Optional[Any] = None, # PdfReader width: Union[float, Decimal, None] = None, height: Union[float, Decimal, None] = None, - ) -> "PageObject": # pragma: no cover + ) -> "PageObject": # deprecated """ .. deprecated:: 1.28.0 @@ -548,11 +548,11 @@ def rotate(self, angle: int) -> "PageObject": self[NameObject(PG.ROTATE)] = NumberObject(current_angle + angle) return self - def rotate_clockwise(self, angle: int) -> "PageObject": # pragma: no cover + def rotate_clockwise(self, angle: int) -> "PageObject": # deprecated deprecation_with_replacement("rotate_clockwise", "rotate", "3.0.0") return self.rotate(angle) - def rotateClockwise(self, angle: int) -> "PageObject": # pragma: no cover + def rotateClockwise(self, angle: int) -> "PageObject": # deprecated """ .. deprecated:: 1.28.0 @@ -561,7 +561,7 @@ def rotateClockwise(self, angle: int) -> "PageObject": # pragma: no cover deprecation_with_replacement("rotateClockwise", "rotate", "3.0.0") return self.rotate(angle) - def rotateCounterClockwise(self, angle: int) -> "PageObject": # pragma: no cover + def rotateCounterClockwise(self, angle: int) -> "PageObject": # deprecated """ .. deprecated:: 1.28.0 @@ -657,7 +657,7 @@ def get_contents(self) -> Optional[ContentStream]: else: return None - def getContents(self) -> Optional[ContentStream]: # pragma: no cover + def getContents(self) -> Optional[ContentStream]: # deprecated """ .. deprecated:: 1.28.0 @@ -684,7 +684,7 @@ def merge_page(self, page2: "PageObject", expand: bool = False) -> None: """ self._merge_page(page2, expand=expand) - def mergePage(self, page2: "PageObject") -> None: # pragma: no cover + def mergePage(self, page2: "PageObject") -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -841,7 +841,7 @@ def mergeTransformedPage( page2: "PageObject", ctm: Union[CompressedTransformationMatrix, Transformation], expand: bool = False, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ mergeTransformedPage is similar to merge_page, but a transformation matrix is applied to the merged stream. @@ -876,7 +876,7 @@ def mergeTransformedPage( def mergeScaledPage( self, page2: "PageObject", scale: float, expand: bool = False - ) -> None: # pragma: no cover + ) -> None: # deprecated """ mergeScaledPage is similar to merge_page, but the stream to be merged is scaled by applying a transformation matrix. @@ -901,7 +901,7 @@ def mergeScaledPage( def mergeRotatedPage( self, page2: "PageObject", rotation: float, expand: bool = False - ) -> None: # pragma: no cover + ) -> None: # deprecated """ mergeRotatedPage is similar to merge_page, but the stream to be merged is rotated by applying a transformation matrix. @@ -926,7 +926,7 @@ def mergeRotatedPage( def mergeTranslatedPage( self, page2: "PageObject", tx: float, ty: float, expand: bool = False - ) -> None: # pragma: no cover + ) -> None: # deprecated """ mergeTranslatedPage is similar to merge_page, but the stream to be merged is translated by applying a transformation matrix. @@ -957,7 +957,7 @@ def mergeRotatedTranslatedPage( tx: float, ty: float, expand: bool = False, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ mergeRotatedTranslatedPage is similar to merge_page, but the stream to be merged is rotated and translated by applying a transformation matrix. @@ -984,7 +984,7 @@ def mergeRotatedTranslatedPage( def mergeRotatedScaledPage( self, page2: "PageObject", rotation: float, scale: float, expand: bool = False - ) -> None: # pragma: no cover + ) -> None: # deprecated """ mergeRotatedScaledPage is similar to merge_page, but the stream to be merged is rotated and scaled by applying a transformation matrix. @@ -1015,7 +1015,7 @@ def mergeScaledTranslatedPage( tx: float, ty: float, expand: bool = False, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ mergeScaledTranslatedPage is similar to merge_page, but the stream to be merged is translated and scaled by applying a transformation matrix. @@ -1048,7 +1048,7 @@ def mergeRotatedScaledTranslatedPage( tx: float, ty: float, expand: bool = False, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ mergeRotatedScaledTranslatedPage is similar to merge_page, but the stream to be merged is translated, rotated and scaled by applying a @@ -1134,7 +1134,7 @@ def add_transformation( def addTransformation( self, ctm: CompressedTransformationMatrix - ) -> None: # pragma: no cover + ) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1206,7 +1206,7 @@ def scale_by(self, factor: float) -> None: """ self.scale(factor, factor) - def scaleBy(self, factor: float) -> None: # pragma: no cover + def scaleBy(self, factor: float) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1228,7 +1228,7 @@ def scale_to(self, width: float, height: float) -> None: sy = height / float(self.mediabox.height) self.scale(sx, sy) - def scaleTo(self, width: float, height: float) -> None: # pragma: no cover + def scaleTo(self, width: float, height: float) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1251,7 +1251,7 @@ def compress_content_streams(self) -> None: content = ContentStream(content, self.pdf) self[NameObject(PG.CONTENTS)] = content.flate_encode() - def compressContentStreams(self) -> None: # pragma: no cover + def compressContentStreams(self) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1888,9 +1888,7 @@ def extract_xform_text( visitor_text, ) - def extractText( - self, Tj_sep: str = "", TJ_sep: str = "" - ) -> str: # pragma: no cover + def extractText(self, Tj_sep: str = "", TJ_sep: str = "") -> str: # deprecated """ .. deprecated:: 1.28.0 @@ -1919,7 +1917,7 @@ def _get_fonts(self) -> Tuple[Set[str], Set[str]]: """ @property - def mediaBox(self) -> RectangleObject: # pragma: no cover + def mediaBox(self) -> RectangleObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1929,7 +1927,7 @@ def mediaBox(self) -> RectangleObject: # pragma: no cover return self.mediabox @mediaBox.setter - def mediaBox(self, value: RectangleObject) -> None: # pragma: no cover + def mediaBox(self, value: RectangleObject) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1948,7 +1946,7 @@ def mediaBox(self, value: RectangleObject) -> None: # pragma: no cover """ @property - def cropBox(self) -> RectangleObject: # pragma: no cover + def cropBox(self) -> RectangleObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1958,7 +1956,7 @@ def cropBox(self) -> RectangleObject: # pragma: no cover return self.cropbox @cropBox.setter - def cropBox(self, value: RectangleObject) -> None: # pragma: no cover + def cropBox(self, value: RectangleObject) -> None: # deprecated deprecation_with_replacement("cropBox", "cropbox", "3.0.0") self.cropbox = value @@ -1970,7 +1968,7 @@ def cropBox(self, value: RectangleObject) -> None: # pragma: no cover """ @property - def bleedBox(self) -> RectangleObject: # pragma: no cover + def bleedBox(self) -> RectangleObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1980,7 +1978,7 @@ def bleedBox(self) -> RectangleObject: # pragma: no cover return self.bleedbox @bleedBox.setter - def bleedBox(self, value: RectangleObject) -> None: # pragma: no cover + def bleedBox(self, value: RectangleObject) -> None: # deprecated deprecation_with_replacement("bleedBox", "bleedbox", "3.0.0") self.bleedbox = value @@ -1991,7 +1989,7 @@ def bleedBox(self, value: RectangleObject) -> None: # pragma: no cover """ @property - def trimBox(self) -> RectangleObject: # pragma: no cover + def trimBox(self) -> RectangleObject: # deprecated """ .. deprecated:: 1.28.0 @@ -2001,7 +1999,7 @@ def trimBox(self) -> RectangleObject: # pragma: no cover return self.trimbox @trimBox.setter - def trimBox(self, value: RectangleObject) -> None: # pragma: no cover + def trimBox(self, value: RectangleObject) -> None: # deprecated deprecation_with_replacement("trimBox", "trimbox", "3.0.0") self.trimbox = value @@ -2013,7 +2011,7 @@ def trimBox(self, value: RectangleObject) -> None: # pragma: no cover """ @property - def artBox(self) -> RectangleObject: # pragma: no cover + def artBox(self) -> RectangleObject: # deprecated """ .. deprecated:: 1.28.0 @@ -2023,7 +2021,7 @@ def artBox(self) -> RectangleObject: # pragma: no cover return self.artbox @artBox.setter - def artBox(self, value: RectangleObject) -> None: # pragma: no cover + def artBox(self, value: RectangleObject) -> None: # deprecated deprecation_with_replacement("artBox", "artbox", "3.0.0") self.artbox = value diff --git a/pypdf/_page_labels.py b/pypdf/_page_labels.py index cad3e48a1..ee80687cb 100644 --- a/pypdf/_page_labels.py +++ b/pypdf/_page_labels.py @@ -116,7 +116,16 @@ def number2lowercase_letter(number: int) -> str: def index2label(reader: PdfReaderProtocol, index: int) -> str: - """See 7.9.7 "Number Trees".""" + """ + See 7.9.7 "Number Trees". + + Args: + reader: The PdfReader + index: The index of the page + + Returns: + The label of the page, e.g. "iv" or "4". + """ root = reader.trailer["/Root"] if "/PageLabels" not in root: return str(index + 1) # Fallback diff --git a/pypdf/_protocols.py b/pypdf/_protocols.py index b8d9498e7..1351310fa 100644 --- a/pypdf/_protocols.py +++ b/pypdf/_protocols.py @@ -30,7 +30,7 @@ def get_object(self) -> Optional["PdfObjectProtocol"]: ... -class PdfReaderProtocol(Protocol): # pragma: no cover +class PdfReaderProtocol(Protocol): # deprecated @property def pdf_header(self) -> str: ... @@ -55,7 +55,7 @@ def get_object(self, indirect_reference: Any) -> Optional[PdfObjectProtocol]: ... -class PdfWriterProtocol(Protocol): # pragma: no cover +class PdfWriterProtocol(Protocol): # deprecated _objects: List[Any] _id_translated: Dict[int, Dict[int, int]] diff --git a/pypdf/_reader.py b/pypdf/_reader.py index 2790f34fb..3eb93707f 100644 --- a/pypdf/_reader.py +++ b/pypdf/_reader.py @@ -110,9 +110,7 @@ def convert_to_int(d: bytes, size: int) -> Union[int, Tuple[Any, ...]]: return struct.unpack(">q", d)[0] -def convertToInt( - d: bytes, size: int -) -> Union[int, Tuple[Any, ...]]: # pragma: no cover +def convertToInt(d: bytes, size: int) -> Union[int, Tuple[Any, ...]]: # deprecated deprecation_with_replacement("convertToInt", "convert_to_int") return convert_to_int(d, size) @@ -140,7 +138,7 @@ def _get_text(self, key: str) -> Optional[str]: return retval return None - def getText(self, key: str) -> Optional[str]: # pragma: no cover + def getText(self, key: str) -> Optional[str]: # deprecated """ The text value of the specified key or None. @@ -284,13 +282,14 @@ class PdfReader: This operation can take some time, as the PDF stream's cross-reference tables are read into memory. - :param stream: A File object or an object that supports the standard read + Args: + stream: A File object or an object that supports the standard read and seek methods similar to a File object. Could also be a string representing a path to a PDF file. - :param bool strict: Determines whether user should be warned of all + strict: Determines whether user should be warned of all problems and also causes some correctable problems to be fatal. Defaults to ``False``. - :param None/str/bytes password: Decrypt PDF file at initialization. If the + password: Decrypt PDF file at initialization. If the password is None, the file will not be decrypted. Defaults to ``None`` """ @@ -365,7 +364,8 @@ def metadata(self) -> Optional[DocumentInformation]: dictionaries, and these metadata streams will not be accessed by this function. - :return: the document information of this PDF file + Returns: + The document information of this PDF file. """ if TK.INFO not in self.trailer: return None @@ -378,7 +378,7 @@ def metadata(self) -> Optional[DocumentInformation]: retval.update(obj) # type: ignore return retval - def getDocumentInfo(self) -> Optional[DocumentInformation]: # pragma: no cover + def getDocumentInfo(self) -> Optional[DocumentInformation]: # deprecated """ .. deprecated:: 1.28.0 @@ -388,7 +388,7 @@ def getDocumentInfo(self) -> Optional[DocumentInformation]: # pragma: no cover return self.metadata @property - def documentInfo(self) -> Optional[DocumentInformation]: # pragma: no cover + def documentInfo(self) -> Optional[DocumentInformation]: # deprecated """ .. deprecated:: 1.28.0 @@ -412,7 +412,7 @@ def xmp_metadata(self) -> Optional[XmpInformation]: finally: self._override_encryption = False - def getXmpMetadata(self) -> Optional[XmpInformation]: # pragma: no cover + def getXmpMetadata(self) -> Optional[XmpInformation]: # deprecated """ .. deprecated:: 1.28.0 @@ -422,7 +422,7 @@ def getXmpMetadata(self) -> Optional[XmpInformation]: # pragma: no cover return self.xmp_metadata @property - def xmpMetadata(self) -> Optional[XmpInformation]: # pragma: no cover + def xmpMetadata(self) -> Optional[XmpInformation]: # deprecated """ .. deprecated:: 1.28.0 @@ -435,8 +435,13 @@ def _get_num_pages(self) -> int: """ Calculate the number of pages in this PDF file. - :return: number of pages - :raises PdfReadError: if file is encrypted and restrictions prevent + Args: + + Returns: + The number of pages of the parsed PDF file + + Raises: + PdfReadError: if file is encrypted and restrictions prevent this action. """ # Flattened pages will not work on an Encrypted PDF; @@ -449,7 +454,7 @@ def _get_num_pages(self) -> int: self._flatten() return len(self.flattened_pages) # type: ignore - def getNumPages(self) -> int: # pragma: no cover + def getNumPages(self) -> int: # deprecated """ .. deprecated:: 1.28.0 @@ -459,7 +464,7 @@ def getNumPages(self) -> int: # pragma: no cover return self._get_num_pages() @property - def numPages(self) -> int: # pragma: no cover + def numPages(self) -> int: # deprecated """ .. deprecated:: 1.28.0 @@ -468,7 +473,7 @@ def numPages(self) -> int: # pragma: no cover deprecation_with_replacement("reader.numPages", "len(reader.pages)", "3.0.0") return self._get_num_pages() - def getPage(self, pageNumber: int) -> PageObject: # pragma: no cover + def getPage(self, pageNumber: int) -> PageObject: # deprecated """ .. deprecated:: 1.28.0 @@ -483,9 +488,12 @@ def _get_page(self, page_number: int) -> PageObject: """ Retrieve a page by number from this PDF file. - :param int page_number: The page number to retrieve + Args: + page_number: The page number to retrieve (pages begin at zero) - :return: a :class:`PageObject` instance. + + Returns: + A :class:`PageObject` instance. """ # ensure that we're not trying to access an encrypted PDF # assert not self.trailer.has_key(TK.ENCRYPT) @@ -495,7 +503,7 @@ def _get_page(self, page_number: int) -> PageObject: return self.flattened_pages[page_number] @property - def namedDestinations(self) -> Dict[str, Any]: # pragma: no cover + def namedDestinations(self) -> Dict[str, Any]: # deprecated """ .. deprecated:: 1.28.0 @@ -526,12 +534,18 @@ def get_fields( The *tree* and *retval* parameters are for recursive use. - :param fileobj: A file object (usually a text file) to write + Args: + tree: (Default value = None) + retval: + fileobj: A file object (usually a text file) to write a report to on all interactive form fields found. - :return: A dictionary where each key is a field name, and each - value is a :class:`Field` object. By - default, the mapping name is used for keys. - ``None`` if form data could not be located. + + Returns: + A dictionary where each key is a field name, and each + value is a :class:`Field` object. By + default, the mapping name is used for keys. + ``None`` if form data could not be located. + """ field_attributes = FieldDictionaryAttributes.attributes_dict() field_attributes.update(CheckboxRadioButtonAttributes.attributes_dict()) @@ -565,7 +579,7 @@ def getFields( tree: Optional[TreeObject] = None, retval: Optional[Dict[Any, Any]] = None, fileobj: Optional[Any] = None, - ) -> Optional[Dict[str, Any]]: # pragma: no cover + ) -> Optional[Dict[str, Any]]: # deprecated """ .. deprecated:: 1.28.0 @@ -660,7 +674,7 @@ def get_form_text_fields(self) -> Dict[str, Any]: if formfields[field].get("/FT") == "/Tx" } - def getFormTextFields(self) -> Dict[str, Any]: # pragma: no cover + def getFormTextFields(self) -> Dict[str, Any]: # deprecated """ .. deprecated:: 1.28.0 @@ -679,7 +693,12 @@ def _get_named_destinations( """ Retrieve the named destinations present in the document. - :return: a dictionary which maps names to + Args: + tree: + retval: + + Returns: + A dictionary which maps names to :class:`Destinations`. """ if retval is None: @@ -724,7 +743,7 @@ def getNamedDestinations( self, tree: Union[TreeObject, None] = None, retval: Optional[Any] = None, - ) -> Dict[str, Any]: # pragma: no cover + ) -> Dict[str, Any]: # deprecated """ .. deprecated:: 1.28.0 @@ -746,7 +765,7 @@ def outline(self) -> OutlineType: return self._get_outline() @property - def outlines(self) -> OutlineType: # pragma: no cover + def outlines(self) -> OutlineType: # deprecated """ .. deprecated:: 2.9.0 @@ -798,7 +817,7 @@ def _get_outline( def getOutlines( self, node: Optional[DictionaryObject] = None, outline: Optional[Any] = None - ) -> OutlineType: # pragma: no cover + ) -> OutlineType: # deprecated """ .. deprecated:: 1.28.0 @@ -824,7 +843,14 @@ def threads(self) -> Optional[ArrayObject]: def _get_page_number_by_indirect( self, indirect_reference: Union[None, int, NullObject, IndirectObject] ) -> int: - """Generate _page_id2num""" + """Generate _page_id2num + + Args: + indirect_reference: + + Returns: + The page number. + """ if self._page_id2num is None: self._page_id2num = { x.indirect_reference.idnum: i for i, x in enumerate(self.pages) # type: ignore @@ -844,13 +870,17 @@ def get_page_number(self, page: PageObject) -> int: """ Retrieve page number of a given PageObject - :param PageObject page: The page to get page number. Should be + Args: + page: The page to get page number. Should be an instance of :class:`PageObject` - :return: the page number or -1 if page not found + page: + + Returns: + The page number or -1 if page not found """ return self._get_page_number_by_indirect(page.indirect_reference) - def getPageNumber(self, page: PageObject) -> int: # pragma: no cover + def getPageNumber(self, page: PageObject) -> int: # deprecated """ .. deprecated:: 1.28.0 @@ -863,14 +893,15 @@ def get_destination_page_number(self, destination: Destination) -> int: """ Retrieve page number of a given Destination object. - :param Destination destination: The destination to get page number. - :return: the page number or -1 if page not found + Args: + destination: The destination to get page number. + + Returns: + The page number or -1 if page not found """ return self._get_page_number_by_indirect(destination.page) - def getDestinationPageNumber( - self, destination: Destination - ) -> int: # pragma: no cover + def getDestinationPageNumber(self, destination: Destination) -> int: # deprecated """ .. deprecated:: 1.28.0 @@ -1026,7 +1057,7 @@ def page_layout(self) -> Optional[str]: return cast(NameObject, trailer[CD.PAGE_LAYOUT]) return None - def getPageLayout(self) -> Optional[str]: # pragma: no cover + def getPageLayout(self) -> Optional[str]: # deprecated """ .. deprecated:: 1.28.0 @@ -1036,7 +1067,7 @@ def getPageLayout(self) -> Optional[str]: # pragma: no cover return self.page_layout @property - def pageLayout(self) -> Optional[str]: # pragma: no cover + def pageLayout(self) -> Optional[str]: # deprecated """ .. deprecated:: 1.28.0 @@ -1073,7 +1104,7 @@ def page_mode(self) -> Optional[PagemodeType]: except KeyError: return None - def getPageMode(self) -> Optional[PagemodeType]: # pragma: no cover + def getPageMode(self) -> Optional[PagemodeType]: # deprecated """ .. deprecated:: 1.28.0 @@ -1083,7 +1114,7 @@ def getPageMode(self) -> Optional[PagemodeType]: # pragma: no cover return self.page_mode @property - def pageMode(self) -> Optional[PagemodeType]: # pragma: no cover + def pageMode(self) -> Optional[PagemodeType]: # deprecated """ .. deprecated:: 1.28.0 @@ -1194,8 +1225,15 @@ def _get_object_from_stream( def _get_indirect_object(self, num: int, gen: int) -> Optional[PdfObject]: """ - used to ease development - equivalent to generic.IndirectObject(num,gen,self).get_object() + Used to ease development. + This is equivalent to generic.IndirectObject(num,gen,self).get_object() + + Args: + num: + gen: + + Returns: + A PdfObject """ return IndirectObject(num, gen, self).get_object() @@ -1331,7 +1369,7 @@ def get_object( def getObject( self, indirectReference: IndirectObject - ) -> Optional[PdfObject]: # pragma: no cover + ) -> Optional[PdfObject]: # deprecated """ .. deprecated:: 1.28.0 @@ -1368,9 +1406,7 @@ def read_object_header(self, stream: StreamType) -> Tuple[int, int]: ) return int(idnum), int(generation) - def readObjectHeader( - self, stream: StreamType - ) -> Tuple[int, int]: # pragma: no cover + def readObjectHeader(self, stream: StreamType) -> Tuple[int, int]: # deprecated """ .. deprecated:: 1.28.0 @@ -1386,7 +1422,7 @@ def cache_get_indirect_object( def cacheGetIndirectObject( self, generation: int, idnum: int - ) -> Optional[PdfObject]: # pragma: no cover + ) -> Optional[PdfObject]: # deprecated """ .. deprecated:: 1.28.0 @@ -1412,7 +1448,7 @@ def cache_indirect_object( def cacheIndirectObject( self, generation: int, idnum: int, obj: Optional[PdfObject] - ) -> Optional[PdfObject]: # pragma: no cover + ) -> Optional[PdfObject]: # deprecated """ .. deprecated:: 1.28.0 @@ -1483,7 +1519,15 @@ def _find_eof_marker(self, stream: StreamType) -> None: line = read_previous_line(stream) def _find_startxref_pos(self, stream: StreamType) -> int: - """Find startxref entry - the location of the xref table""" + """ + Find startxref entry - the location of the xref table. + + Args: + stream: + + Returns: + The bytes offset + """ line = read_previous_line(stream) try: startxref = int(line) @@ -1765,7 +1809,16 @@ def used_before(num: int, generation: Union[int, Tuple[int, ...]]) -> bool: @staticmethod def _get_xref_issues(stream: StreamType, startxref: int) -> int: - """Return an int which indicates an issue. 0 means there is no issue.""" + """ + Return an int which indicates an issue. 0 means there is no issue. + + Args: + stream: + startxref: + + Returns: + 0 means no issue, other values represent specific issues. + """ stream.seek(startxref - 1, 0) # -1 to check character before line = stream.read(1) if line not in b"\r\n \t": @@ -1854,7 +1907,7 @@ def _pairs(self, array: List[int]) -> Iterable[Tuple[int, int]]: def read_next_end_line( self, stream: StreamType, limit_offset: int = 0 - ) -> bytes: # pragma: no cover + ) -> bytes: # deprecated """.. deprecated:: 2.1.0""" deprecate_no_replacement("read_next_end_line", removed_in="4.0.0") line_parts = [] @@ -1887,7 +1940,7 @@ def read_next_end_line( def readNextEndLine( self, stream: StreamType, limit_offset: int = 0 - ) -> bytes: # pragma: no cover + ) -> bytes: # deprecated """.. deprecated:: 1.28.0""" deprecation_no_replacement("readNextEndLine", "3.0.0") return self.read_next_end_line(stream, limit_offset) @@ -1904,8 +1957,11 @@ def decrypt(self, password: Union[str, bytes]) -> PasswordType: the correct decryption key that will allow the document to be used with this library. - :param str password: The password to match. - :return: `PasswordType`. + Args: + password: The password to match. + + Returns: + A `PasswordType`. """ if not self._encryption: raise PdfReadError("Not encrypted file") @@ -1936,7 +1992,7 @@ def is_encrypted(self) -> bool: """ return TK.ENCRYPT in self.trailer - def getIsEncrypted(self) -> bool: # pragma: no cover + def getIsEncrypted(self) -> bool: # deprecated """ .. deprecated:: 1.28.0 @@ -1946,7 +2002,7 @@ def getIsEncrypted(self) -> bool: # pragma: no cover return self.is_encrypted @property - def isEncrypted(self) -> bool: # pragma: no cover + def isEncrypted(self) -> bool: # deprecated """ .. deprecated:: 1.28.0 @@ -1980,7 +2036,7 @@ def xfa(self) -> Optional[Dict[str, Any]]: return retval -class PdfFileReader(PdfReader): # pragma: no cover +class PdfFileReader(PdfReader): # deprecated def __init__(self, *args: Any, **kwargs: Any) -> None: deprecation_with_replacement("PdfFileReader", "PdfReader", "3.0.0") if "strict" not in kwargs and len(args) < 2: diff --git a/pypdf/_security.py b/pypdf/_security.py index ab9b594fc..b2314f32c 100644 --- a/pypdf/_security.py +++ b/pypdf/_security.py @@ -64,6 +64,22 @@ def _alg32( Implementation of algorithm 3.2 of the PDF standard security handler. See section 3.5.2 of the PDF 1.6 reference. + + Args: + password: The encryption secret as a bytes-string + rev: The encryption revision (see PDF standard) + keylen: + owner_entry: + p_entry: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, all other + bits are ignored and all operations are permitted. If bit 2 is set to 0, + permission for operations are based on the values of the remaining flags + defined in Table 24. + id1_entry: + metadata_encrypt: (Default value = True) + + Returns: + An MD5 hash of keylen characters. """ # 1. Pad or truncate the password string to exactly 32 bytes. If the # password string is more than 32 bytes long, use only its first 32 bytes; @@ -111,6 +127,15 @@ def _alg33( """ Implementation of algorithm 3.3 of the PDF standard security handler, section 3.5.2 of the PDF 1.6 reference. + + Args: + owner_password: + user_password: + rev: The encryption revision (see PDF standard) + keylen: + + Returns: + A transformed version of the owner and the user password """ # steps 1 - 4 key = _alg33_1(owner_password, rev, keylen) @@ -136,7 +161,17 @@ def _alg33( def _alg33_1(password: str, rev: Literal[2, 3, 4], keylen: int) -> bytes: - """Steps 1-4 of algorithm 3.3""" + """ + Steps 1-4 of algorithm 3.3 + + Args: + password: + rev: The encryption revision (see PDF standard) + keylen: + + Returns: + A transformed version of the password + """ # 1. Pad or truncate the owner password string as described in step 1 of # algorithm 3.2. If there is no owner password, use the user password # instead. @@ -168,6 +203,19 @@ def _alg34( Implementation of algorithm 3.4 of the PDF standard security handler. See section 3.5.2 of the PDF 1.6 reference. + + Args: + password: + owner_entry: + p_entry: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, all other + bits are ignored and all operations are permitted. If bit 2 is set to 0, + permission for operations are based on the values of the remaining flags + defined in Table 24. + id1_entry: + + Returns: + A Tuple (u-value, key) """ # 1. Create an encryption key based on the user password string, as # described in algorithm 3.2. @@ -196,6 +244,22 @@ def _alg35( Implementation of algorithm 3.4 of the PDF standard security handler. See section 3.5.2 of the PDF 1.6 reference. + + Args: + password: + rev: The encryption revision (see PDF standard) + keylen: + owner_entry: + p_entry: A set of flags specifying which operations shall be permitted + when the document is opened with user access. If bit 2 is set to 1, all other + bits are ignored and all operations are permitted. If bit 2 is set to 0, + permission for operations are based on the values of the remaining flags + defined in Table 24. + id1_entry: + metadata_encrypt: A boolean + + Returns: + A tuple (value, key) """ # 1. Create an encryption key based on the user password string, as # described in Algorithm 3.2. diff --git a/pypdf/_utils.py b/pypdf/_utils.py index 0ef507f14..4da2663fc 100644 --- a/pypdf/_utils.py +++ b/pypdf/_utils.py @@ -100,6 +100,13 @@ def read_until_whitespace(stream: StreamType, maxchars: Optional[int] = None) -> Read non-whitespace characters and return them. Stops upon encountering whitespace or when maxchars is reached. + + Args: + stream: The data stream from which was read. + maxchars: The maximum number of bytes returned; by default unlimited. + + Returns: + The data which was read. """ txt = b"" while True: @@ -113,7 +120,15 @@ def read_until_whitespace(stream: StreamType, maxchars: Optional[int] = None) -> def read_non_whitespace(stream: StreamType) -> bytes: - """Find and read the next non-whitespace character (ignores whitespace).""" + """ + Find and read the next non-whitespace character (ignores whitespace). + + Args: + stream: The data stream from which was read. + + Returns: + The data which was read. + """ tok = stream.read(1) while tok in WHITESPACES: tok = stream.read(1) @@ -122,8 +137,15 @@ def read_non_whitespace(stream: StreamType) -> bytes: def skip_over_whitespace(stream: StreamType) -> bool: """ - Similar to read_non_whitespace, but return a Boolean if more than + Similar to read_non_whitespace, but return a boolean if more than one whitespace character was read. + + Args: + stream: The data stream from which was read. + + Returns: + True if more than one whitespace was skipped, + otherwise return False. """ tok = WHITESPACES[0] cnt = 0 @@ -147,9 +169,17 @@ def read_until_regex( """ Read until the regular expression pattern matched (ignore the match). - :raises PdfStreamError: on premature end-of-file - :param bool ignore_eof: If true, ignore end-of-line and return immediately - :param regex: re.Pattern + Args: + ignore_eof: If true, ignore end-of-line and return immediately + regex: re.Pattern + ignore_eof: (Default value = False) + + Returns: + The read bytes. + + Raises: + PdfStreamError: on premature end-of-file + """ name = b"" while True: @@ -173,6 +203,13 @@ def read_block_backwards(stream: StreamType, to_read: int) -> bytes: This changes the stream's position to the beginning of where the block was read. + + Args: + stream: + to_read: + + Returns: + The data which was read. """ if stream.tell() < to_read: raise PdfStreamError("Could not read malformed PDF file") @@ -193,6 +230,12 @@ def read_previous_line(stream: StreamType) -> bytes: After this call, the stream will be positioned one byte after the first non-CRLF character found beyond the first CR/LF byte before X, or, if no such byte is found, at the beginning of the stream. + + Args: + stream: StreamType: + + Returns: + The data which was read. """ line_content = [] found_crlf = False diff --git a/pypdf/_writer.py b/pypdf/_writer.py index 2aa1464af..774ed20af 100644 --- a/pypdf/_writer.py +++ b/pypdf/_writer.py @@ -132,8 +132,9 @@ class PdfWriter: """ - This class supports writing PDF files out, given pages produced by another - class (typically :class:`PdfReader`). + Write a PDF file out, given pages produced by another class. + + Typically data is added from a :class:`PdfReader`. """ def __init__(self, fileobj: StrByteType = "") -> None: @@ -238,9 +239,7 @@ def get_object( raise ValueError("pdf must be self") return self._objects[indirect_reference.idnum - 1] # type: ignore - def getObject( - self, ido: Union[int, IndirectObject] - ) -> PdfObject: # pragma: no cover + def getObject(self, ido: Union[int, IndirectObject]) -> PdfObject: # deprecated """ .. deprecated:: 1.28.0 @@ -315,8 +314,13 @@ def add_page( The page is usually acquired from a :class:`PdfReader` instance. - :param PageObject page: The page to add to the document. Should be + Args: + page: The page to add to the document. Should be an instance of :class:`PageObject` + excluded_keys: (Default value = ()) + + Returns: + The added PageObject. """ return self._add_page(page, list.append, excluded_keys) @@ -324,7 +328,7 @@ def addPage( self, page: PageObject, excluded_keys: Iterable[str] = (), - ) -> PageObject: # pragma: no cover + ) -> PageObject: # deprecated """ .. deprecated:: 1.28.0 @@ -343,8 +347,13 @@ def insert_page( Insert a page in this PDF file. The page is usually acquired from a :class:`PdfReader` instance. - :param PageObject page: The page to add to the document. - :param int index: Position at which the page will be inserted. + Args: + page: The page to add to the document. + index: Position at which the page will be inserted. + excluded_keys: (Default value = ()) + + Returns: + The added PageObject. """ return self._add_page(page, lambda l, p: l.insert(index, p)) @@ -353,7 +362,7 @@ def insertPage( page: PageObject, index: int = 0, excluded_keys: Iterable[str] = (), - ) -> PageObject: # pragma: no cover + ) -> PageObject: # deprecated """ .. deprecated:: 1.28.0 @@ -368,24 +377,27 @@ def get_page( """ Retrieve a page by number from this PDF file. - :param int page_number: The page number to retrieve + Args: + page_number: The page number to retrieve (pages begin at zero) - :return: the page at the index given by *page_number* + + Returns: + The page at the index given by *page_number* """ - if pageNumber is not None: # pragma: no cover + if pageNumber is not None: # deprecated if page_number is not None: raise ValueError("Please only use the page_number parameter") 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: # pragma: no cover + if page_number is None and pageNumber is None: # deprecated raise ValueError("Please specify the page_number") pages = cast(Dict[str, Any], self.get_object(self._pages)) # TODO: crude hack return cast(PageObject, pages[PA.KIDS][page_number].get_object()) - def getPage(self, pageNumber: int) -> PageObject: # pragma: no cover + def getPage(self, pageNumber: int) -> PageObject: # deprecated """ .. deprecated:: 1.28.0 @@ -398,7 +410,7 @@ def _get_num_pages(self) -> int: pages = cast(Dict[str, Any], self.get_object(self._pages)) return int(pages[NameObject("/Count")]) - def getNumPages(self) -> int: # pragma: no cover + def getNumPages(self) -> int: # deprecated """ .. deprecated:: 1.28.0 @@ -419,12 +431,17 @@ def add_blank_page( Append a blank page to this PDF file and returns it. If no page size is specified, use the size of the last page. - :param float width: The width of the new page expressed in default user + Args: + width: The width of the new page expressed in default user space units. - :param float height: The height of the new page expressed in default + height: The height of the new page expressed in default user space units. - :return: the newly appended page - :raises PageSizeNotDefinedError: if width and height are not defined + + Returns: + The newly appended page + + Raises: + PageSizeNotDefinedError: if width and height are not defined and previous page does not exist. """ page = PageObject.create_blank_page(self, width, height) @@ -433,7 +450,7 @@ def add_blank_page( def addBlankPage( self, width: Optional[float] = None, height: Optional[float] = None - ) -> PageObject: # pragma: no cover + ) -> PageObject: # deprecated """ .. deprecated:: 1.28.0 @@ -452,13 +469,18 @@ def insert_blank_page( Insert a blank page to this PDF file and returns it. If no page size is specified, use the size of the last page. - :param float width: The width of the new page expressed in default user + Args: + width: The width of the new page expressed in default user space units. - :param float height: The height of the new page expressed in default + height: The height of the new page expressed in default user space units. - :param int index: Position to add the page. - :return: the newly appended page - :raises PageSizeNotDefinedError: if width and height are not defined + index: Position to add the page. + + Returns: + The newly appended page + + Raises: + PageSizeNotDefinedError: if width and height are not defined and previous page does not exist. """ if width is None or height is None and (self._get_num_pages() - 1) >= index: @@ -474,7 +496,7 @@ def insertBlankPage( width: Optional[decimal.Decimal] = None, height: Optional[decimal.Decimal] = None, index: int = 0, - ) -> PageObject: # pragma: no cover + ) -> PageObject: # deprecated """ .. deprecated:: 1.28.0 @@ -492,7 +514,8 @@ def open_destination( PDF catalog). it returns `None` if the entry does not exist is not set. - :param destination: the property can be set to a Destination, + Args: + destination: the property can be set to a Destination, a Page or an string(NamedDest) or None (to remove "/OpenAction") @@ -538,7 +561,8 @@ def add_js(self, javascript: str) -> None: """ Add Javascript which will launch upon opening this PDF. - :param str javascript: Your Javascript. + Args: + javascript: Your Javascript. >>> output.add_js("this.print({bUI:true,bSilent:false,bShrinkToFit:true});") # Example: This will launch the print window when the PDF is opened. @@ -568,7 +592,7 @@ def add_js(self, javascript: str) -> None: js_list.append(create_string_object(str(uuid.uuid4()))) js_list.append(self._add_object(js)) - def addJS(self, javascript: str) -> None: # pragma: no cover + def addJS(self, javascript: str) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -581,12 +605,13 @@ def add_attachment(self, filename: str, data: Union[str, bytes]) -> None: """ Embed a file inside the PDF. - :param str filename: The filename to display. - :param str data: The data in the file. - Reference: https://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf Section 7.11.3 + + Args: + filename: The filename to display. + data: The data in the file. """ # We need three entries: # * The file's data @@ -659,9 +684,7 @@ def add_attachment(self, filename: str, data: Union[str, bytes]) -> None: # Update the root self._root_object.update({NameObject(CA.NAMES): embedded_files_dictionary}) - def addAttachment( - self, fname: str, fdata: Union[str, bytes] - ) -> None: # pragma: no cover + def addAttachment(self, fname: str, fdata: Union[str, bytes]) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -681,10 +704,11 @@ def append_pages_from_reader( `append` should be prefered. - :param PdfReader reader: a PdfReader object from which to copy page + Args: + reader: a PdfReader object from which to copy page annotations to this writer object. The writer's annots will then be updated - :param Callable[[PageObject], None] after_page_append: + after_page_append: Callback function that is invoked after each page is appended to the writer. Signature includes a reference to the appended page (delegates to append_pages_from_reader). The single parameter of the @@ -704,7 +728,7 @@ def appendPagesFromReader( self, reader: PdfReader, after_page_append: Optional[Callable[[PageObject], None]] = None, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -727,11 +751,12 @@ def update_page_form_field_values( Copy field texts and values from fields to page. If the field links to a parent object, add the information to the parent. - :param PageObject page: Page reference from PDF writer where the + Args: + page: Page reference from PDF writer where the annotations and field data will be updated. - :param dict fields: a Python dictionary of field names (/T) and text + fields: a Python dictionary of field names (/T) and text values (/V) - :param int flags: An integer (0 to 7). The first bit sets ReadOnly, the + flags: An integer (0 to 7). The first bit sets ReadOnly, the second bit sets Required, the third bit sets NoExport. See PDF Reference Table 8.70 for details. """ @@ -785,7 +810,7 @@ def updatePageFormFieldValues( page: PageObject, fields: Dict[str, Any], flags: FieldFlag = OPTIONAL_READ_WRITE_FIELD, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -802,7 +827,8 @@ def clone_reader_document_root(self, reader: PdfReader) -> None: including pages, threads, outlines,... For partial insertion, `append` should be considered. - :param reader: PdfReader from the document root should be copied. + Args: + reader: PdfReader from the document root should be copied. """ self._root_object = cast(DictionaryObject, reader.trailer[TK.ROOT].clone(self)) self._root = self._root_object.indirect_reference # type: ignore[assignment] @@ -813,7 +839,7 @@ def clone_reader_document_root(self, reader: PdfReader) -> None: ] = self.flattened_pages del self.flattened_pages - def cloneReaderDocumentRoot(self, reader: PdfReader) -> None: # pragma: no cover + def cloneReaderDocumentRoot(self, reader: PdfReader) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -875,9 +901,10 @@ def clone_document_from_reader( Create a copy (clone) of a document from a PDF file reader cloning section '/Root' and '/Info' and '/ID' of the pdf - :param reader: PDF file reader instance from which the clone + Args: + reader: PDF file reader instance from which the clone should be created. - :param Callable[[PageObject], None] after_page_append: + after_page_append: Callback function that is invoked after each page is appended to the writer. Signature includes a reference to the appended page (delegates to append_pages_from_reader). The single parameter of the @@ -899,7 +926,7 @@ def cloneDocumentFromReader( self, reader: PdfReader, after_page_append: Optional[Callable[[PageObject], None]] = None, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -922,15 +949,16 @@ def encrypt( """ Encrypt this PDF file with the PDF Standard encryption handler. - :param str user_password: The "user password", which allows for opening + Args: + user_password: The "user password", which allows for opening and reading the PDF file with the restrictions provided. - :param str owner_password: The "owner password", which allows for + owner_password: The "owner password", which allows for opening the PDF files without any restrictions. By default, the owner password is the same as the user password. - :param bool use_128bit: flag as to whether to use 128bit + use_128bit: flag as to whether to use 128bit encryption. When false, 40bit encryption will be used. By default, this flag is on. - :param unsigned int permissions_flag: permissions as described in + permissions_flag: permissions as described in TABLE 3.20 of the PDF 1.7 specification. A bit value of 1 means the permission is grantend. Hence an integer value of -1 will set all flags. @@ -1034,10 +1062,14 @@ def write(self, stream: Union[Path, StrByteType]) -> Tuple[bool, IO]: """ Write the collection of pages added to this object out as a PDF file. - :param stream: An object to write the file to. The object can support + Args: + stream: An object to write the file to. The object can support the write method and the tell method, similar to a file object, or be a file path, just like the fileobj, just named it stream to keep existing workflow. + + Returns: + A tuple (bool, IO) """ my_file = False @@ -1108,7 +1140,8 @@ def add_metadata(self, infos: Dict[str, Any]) -> None: """ Add custom metadata to the output. - :param dict infos: a Python dictionary where each key is a field + Args: + infos: a Python dictionary where each key is a field and each value is your new metadata. """ args = {} @@ -1116,7 +1149,7 @@ def add_metadata(self, infos: Dict[str, Any]) -> None: args[NameObject(key)] = create_string_object(value) self.get_object(self._info).update(args) # type: ignore - def addMetadata(self, infos: Dict[str, Any]) -> None: # pragma: no cover + def addMetadata(self, infos: Dict[str, Any]) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1212,6 +1245,12 @@ def _resolve_indirect_object(self, data: IndirectObject) -> IndirectObject: If it is a new object then it is added to self._objects and new idnum is given and generation is always 0. + + Args: + data: + + Returns: + The resolved indirect object """ if hasattr(data.pdf, "stream") and data.pdf.stream.closed: raise ValueError(f"I/O operation on closed file: {data.pdf.stream.name}") @@ -1250,7 +1289,7 @@ def get_reference(self, obj: PdfObject) -> IndirectObject: assert ref.get_object() == obj return ref - def getReference(self, obj: PdfObject) -> IndirectObject: # pragma: no cover + def getReference(self, obj: PdfObject) -> IndirectObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1297,7 +1336,7 @@ def threads(self) -> ArrayObject: """ return self.get_threads_root() - def getOutlineRoot(self) -> TreeObject: # pragma: no cover + def getOutlineRoot(self) -> TreeObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1341,7 +1380,7 @@ def get_named_dest_root(self) -> ArrayObject: return nd - def getNamedDestRoot(self) -> ArrayObject: # pragma: no cover + def getNamedDestRoot(self) -> ArrayObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1391,7 +1430,7 @@ def add_bookmark_destination( self, dest: Union[PageObject, TreeObject], parent: Union[None, TreeObject, IndirectObject] = None, - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 2.9.0 @@ -1404,7 +1443,7 @@ def add_bookmark_destination( def addBookmarkDestination( self, dest: PageObject, parent: Optional[TreeObject] = None - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1440,7 +1479,7 @@ def add_outline_item_dict( @deprecation_bookmark(bookmark="outline_item") def add_bookmark_dict( self, outline_item: OutlineItemType, parent: Optional[TreeObject] = None - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 2.9.0 @@ -1454,7 +1493,7 @@ def add_bookmark_dict( @deprecation_bookmark(bookmark="outline_item") def addBookmarkDict( self, outline_item: OutlineItemType, parent: Optional[TreeObject] = None - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1480,17 +1519,21 @@ def add_outline_item( """ Add an outline item (commonly referred to as a "Bookmark") to this PDF file. - :param str title: Title to use for this outline item. - :param int page_number: Page number this outline item will point to. - :param parent: A reference to a parent outline item to create nested + Args: + title: Title to use for this outline item. + page_number: Page number this outline item will point to. + parent: A reference to a parent outline item to create nested outline items. - :param parent: A reference to a parent outline item to create nested + parent: A reference to a parent outline item to create nested outline items. - :param tuple color: Color of the outline item's font as a red, green, blue tuple + color: Color of the outline item's font as a red, green, blue tuple from 0.0 to 1.0 or as a Hex String (#RRGGBB) - :param bool bold: Outline item font is bold - :param bool italic: Outline item font is italic - :param Fit fit: The fit of the destination page. + bold: Outline item font is bold + italic: Outline item font is italic + fit: The fit of the destination page. + + Returns: + The added outline item as an indirect object. """ page_ref: Union[None, NullObject, IndirectObject, NumberObject] if isinstance(italic, Fit): # it means that we are on the old params @@ -1551,7 +1594,7 @@ def add_bookmark( italic: bool = False, fit: FitType = "/Fit", *args: ZoomArgType, - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 2.9.0 @@ -1578,7 +1621,7 @@ def addBookmark( italic: bool = False, fit: FitType = "/Fit", *args: ZoomArgType, - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1648,7 +1691,7 @@ def add_named_destination_object( def addNamedDestinationObject( self, dest: Destination - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1702,7 +1745,7 @@ def add_named_destination( def addNamedDestination( self, title: str, pagenum: int - ) -> IndirectObject: # pragma: no cover + ) -> IndirectObject: # deprecated """ .. deprecated:: 1.28.0 @@ -1722,7 +1765,7 @@ def remove_links(self) -> None: if PG.ANNOTS in page_ref: del page_ref[PG.ANNOTS] - def removeLinks(self) -> None: # pragma: no cover + def removeLinks(self) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1735,7 +1778,8 @@ def remove_images(self, ignore_byte_string_object: bool = False) -> None: """ Remove images from this output. - :param bool ignore_byte_string_object: optional parameter + Args: + ignore_byte_string_object: optional parameter to ignore ByteString Objects. """ pg_dict = cast(DictionaryObject, self.get_object(self._pages)) @@ -1808,9 +1852,7 @@ def remove_images(self, ignore_byte_string_object: bool = False) -> None: content.operations = _operations page_ref.__setitem__(NameObject("/Contents"), content) - def removeImages( - self, ignoreByteStringObject: bool = False - ) -> None: # pragma: no cover + def removeImages(self, ignoreByteStringObject: bool = False) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1823,8 +1865,8 @@ def remove_text(self, ignore_byte_string_object: bool = False) -> None: """ Remove text from this output. - :param bool ignore_byte_string_object: optional parameter - to ignore ByteString Objects. + Args: + ignore_byte_string_object: optional parameter to ignore ByteString Objects. """ pg_dict = cast(DictionaryObject, self.get_object(self._pages)) pages = cast(List[IndirectObject], pg_dict[PA.KIDS]) @@ -1863,9 +1905,7 @@ def remove_text(self, ignore_byte_string_object: bool = False) -> None: page_ref.__setitem__(NameObject("/Contents"), content) - def removeText( - self, ignoreByteStringObject: bool = False - ) -> None: # pragma: no cover + def removeText(self, ignoreByteStringObject: bool = False) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -1886,12 +1926,13 @@ def add_uri( Add an URI from a rectangular area to the specified page. This uses the basic structure of :meth:`add_link` - :param int page_number: index of the page on which to place the URI action. - :param str uri: URI of resource to link to. - :param Tuple[int, int, int, int] rect: :class:`RectangleObject` or array of four + Args: + page_number: index of the page on which to place the URI action. + uri: URI of resource to link to. + rect: :class:`RectangleObject` or array of four integers specifying the clickable rectangular area ``[xLL, yLL, xUR, yUR]``, or string in the form ``"[ xLL yLL xUR yUR ]"``. - :param ArrayObject border: if provided, an array describing border-drawing + border: if provided, an array describing border-drawing properties. See the PDF spec for details. No border will be drawn if this argument is omitted. """ @@ -1955,7 +1996,7 @@ def addURI( uri: str, rect: RectangleObject, border: Optional[ArrayObject] = None, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -2003,7 +2044,7 @@ def addLink( border: Optional[ArrayObject] = None, fit: FitType = "/Fit", *args: ZoomArgType, - ) -> None: # pragma: no cover + ) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -2030,7 +2071,7 @@ def _get_page_layout(self) -> Optional[LayoutType]: except KeyError: return None - def getPageLayout(self) -> Optional[LayoutType]: # pragma: no cover + def getPageLayout(self) -> Optional[LayoutType]: # deprecated """ .. deprecated:: 1.28.0 @@ -2043,25 +2084,26 @@ def _set_page_layout(self, layout: Union[NameObject, LayoutType]) -> None: """ Set the page layout. - :param str layout: The page layout to be used. + Args: + str: layout: The page layout to be used. .. list-table:: Valid ``layout`` arguments - :widths: 50 200 - - * - /NoLayout - - Layout explicitly not specified - * - /SinglePage - - Show one page at a time - * - /OneColumn - - Show one column at a time - * - /TwoColumnLeft - - Show pages in two columns, odd-numbered pages on the left - * - /TwoColumnRight - - Show pages in two columns, odd-numbered pages on the right - * - /TwoPageLeft - - Show two pages at a time, odd-numbered pages on the left - * - /TwoPageRight - - Show two pages at a time, odd-numbered pages on the right + :widths: 50 200 + + * - /NoLayout + - Layout explicitly not specified + * - /SinglePage + - Show one page at a time + * - /OneColumn + - Show one column at a time + * - /TwoColumnLeft + - Show pages in two columns, odd-numbered pages on the left + * - /TwoColumnRight + - Show pages in two columns, odd-numbered pages on the right + * - /TwoPageLeft + - Show two pages at a time, odd-numbered pages on the left + * - /TwoPageRight + - Show two pages at a time, odd-numbered pages on the right """ if not isinstance(layout, NameObject): if layout not in self._valid_layouts: @@ -2076,29 +2118,30 @@ def set_page_layout(self, layout: LayoutType) -> None: """ Set the page layout. - :param str layout: The page layout to be used + Args: + layout: The page layout to be used .. list-table:: Valid ``layout`` arguments - :widths: 50 200 - - * - /NoLayout - - Layout explicitly not specified - * - /SinglePage - - Show one page at a time - * - /OneColumn - - Show one column at a time - * - /TwoColumnLeft - - Show pages in two columns, odd-numbered pages on the left - * - /TwoColumnRight - - Show pages in two columns, odd-numbered pages on the right - * - /TwoPageLeft - - Show two pages at a time, odd-numbered pages on the left - * - /TwoPageRight - - Show two pages at a time, odd-numbered pages on the right + :widths: 50 200 + + * - /NoLayout + - Layout explicitly not specified + * - /SinglePage + - Show one page at a time + * - /OneColumn + - Show one column at a time + * - /TwoColumnLeft + - Show pages in two columns, odd-numbered pages on the left + * - /TwoColumnRight + - Show pages in two columns, odd-numbered pages on the right + * - /TwoPageLeft + - Show two pages at a time, odd-numbered pages on the left + * - /TwoPageRight + - Show two pages at a time, odd-numbered pages on the right """ self._set_page_layout(layout) - def setPageLayout(self, layout: LayoutType) -> None: # pragma: no cover + def setPageLayout(self, layout: LayoutType) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -2139,7 +2182,7 @@ def page_layout(self, layout: LayoutType) -> None: self._set_page_layout(layout) @property - def pageLayout(self) -> Optional[LayoutType]: # pragma: no cover + def pageLayout(self) -> Optional[LayoutType]: # deprecated """ .. deprecated:: 1.28.0 @@ -2149,7 +2192,7 @@ def pageLayout(self) -> Optional[LayoutType]: # pragma: no cover return self.page_layout @pageLayout.setter - def pageLayout(self, layout: LayoutType) -> None: # pragma: no cover + def pageLayout(self, layout: LayoutType) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -2173,7 +2216,7 @@ def _get_page_mode(self) -> Optional[PagemodeType]: except KeyError: return None - def getPageMode(self) -> Optional[PagemodeType]: # pragma: no cover + def getPageMode(self) -> Optional[PagemodeType]: # deprecated """ .. deprecated:: 1.28.0 @@ -2198,7 +2241,7 @@ def set_page_mode(self, mode: PagemodeType) -> None: mode_name = NameObject(mode) self._root_object.update({NameObject("/PageMode"): mode_name}) - def setPageMode(self, mode: PagemodeType) -> None: # pragma: no cover + def setPageMode(self, mode: PagemodeType) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -2237,7 +2280,7 @@ def page_mode(self, mode: PagemodeType) -> None: self.set_page_mode(mode) @property - def pageMode(self) -> Optional[PagemodeType]: # pragma: no cover + def pageMode(self) -> Optional[PagemodeType]: # deprecated """ .. deprecated:: 1.28.0 @@ -2247,7 +2290,7 @@ def pageMode(self) -> Optional[PagemodeType]: # pragma: no cover return self.page_mode @pageMode.setter - def pageMode(self, mode: PagemodeType) -> None: # pragma: no cover + def pageMode(self, mode: PagemodeType) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -2285,6 +2328,12 @@ def clean_page(self, page: Union[PageObject, IndirectObject]) -> PageObject: """ Perform some clean up in the page. Currently: convert NameObject nameddestination to TextStringObject (required for names/dests list) + + Args: + page: + + Returns: + The cleaned PageObject """ page = cast("PageObject", page.get_object()) for a in page.get("/Annots", []): @@ -2353,25 +2402,22 @@ def append( concatenate all pages onto the end of the file instead of specifying a position. - :param fileobj: A File Object or an object that supports the standard + Args: + fileobj: A File Object or an object that supports the standard read and seek methods similar to a File Object. Could also be a string representing a path to a PDF file. - - :param str outline_item: Optionally, you may specify a string to build an outline + outline_item: Optionally, you may specify a string to build an outline (aka 'bookmark') to identify the beginning of the included file. - - :param pages: can be a :class:`PageRange` + pages: can be a :class:`PageRange` or a ``(start, stop[, step])`` tuple or a list of pages to be processed to merge only the specified range of pages from the source document into the output document. - - :param bool import_outline: You may prevent the source document's + import_outline: You may prevent the source document's outline (collection of outline items, previously referred to as - 'bookmarks') from being imported by specifying this as ``False``. - - :param List excluded_fields: provide the list of fields/keys to be ignored + 'bookmarks') from being imported by specifying this as ``False``. + excluded_fields: provide the list of fields/keys to be ignored if "/Annots" is part of the list, the annotation will be ignored if "/B" is part of the list, the articles will be ignored """ @@ -2403,28 +2449,24 @@ def merge( Merge the pages from the given file into the output file at the specified page number. - :param int position: The *page number* to insert this file. File will + Args: + position: The *page number* to insert this file. File will be inserted after the given number. - - :param fileobj: A File Object or an object that supports the standard + fileobj: A File Object or an object that supports the standard read and seek methods similar to a File Object. Could also be a string representing a path to a PDF file. - - :param str outline_item: Optionally, you may specify a string to build an outline + outline_item: Optionally, you may specify a string to build an outline (aka 'bookmark') to identify the beginning of the included file. - - :param pages: can be a :class:`PageRange` + pages: can be a :class:`PageRange` or a ``(start, stop[, step])`` tuple or a list of pages to be processed to merge only the specified range of pages from the source document into the output document. - - :param bool import_outline: You may prevent the source document's + import_outline: You may prevent the source document's outline (collection of outline items, previously referred to as 'bookmarks') from being imported by specifying this as ``False``. - - :param List excluded_fields: provide the list of fields/keys to be ignored + excluded_fields: provide the list of fields/keys to be ignored if "/Annots" is part of the list, the annotation will be ignored if "/B" is part of the list, the articles will be ignored """ @@ -2526,8 +2568,15 @@ def _add_articles_thread( reader: PdfReader, ) -> IndirectObject: """ - clone the thread with only the applicable articles + Clone the thread with only the applicable articles + Args: + thread: + pages: + reader: + + Returns: + The added thread as an indirect reference """ nthread = thread.clone( self, force_duplicate=True, ignore_fields=("/F",) @@ -2584,6 +2633,11 @@ def add_filtered_articles( ) -> None: """ Add articles matching the defined criteria + + Args: + fltr: + pages: + reader: """ if isinstance(fltr, str): fltr = re.compile(fltr) @@ -2676,7 +2730,17 @@ def _get_filtered_outline( pages: Dict[int, PageObject], reader: PdfReader, ) -> List[Destination]: - """Extract outline item entries that are part of the specified page set.""" + """ + Extract outline item entries that are part of the specified page set. + + Args: + node: + pages: + reader: + + Returns: + A list of destination objects. + """ new_outline = [] node = node.get_object() if node.get("/Type", "") == "/Outlines" or "/Title" not in node: @@ -2781,7 +2845,7 @@ def find_bookmark( self, outline_item: Dict[str, Any], root: Optional[OutlineType] = None, - ) -> Optional[List[int]]: # pragma: no cover + ) -> Optional[List[int]]: # deprecated """ .. deprecated:: 2.9.0 Use :meth:`find_outline_item` instead. @@ -2795,8 +2859,9 @@ def reset_translation( reset the translation table between reader and the writer object. late cloning will create new independent objects - :param reader: PdfReader or IndirectObject refering a PdfReader object. - if set to None or omitted, all tables will be reset. + Args: + reader: PdfReader or IndirectObject refering a PdfReader object. + if set to None or omitted, all tables will be reset. """ if reader is None: self._id_translated = {} @@ -2878,7 +2943,7 @@ def _create_outline_item( return outline_item -class PdfFileWriter(PdfWriter): # pragma: no cover +class PdfFileWriter(PdfWriter): # deprecated def __init__(self, *args: Any, **kwargs: Any) -> None: deprecation_with_replacement("PdfFileWriter", "PdfWriter", "3.0.0") super().__init__(*args, **kwargs) diff --git a/pypdf/constants.py b/pypdf/constants.py index a2f8c49ed..10b5886fb 100644 --- a/pypdf/constants.py +++ b/pypdf/constants.py @@ -424,9 +424,7 @@ class CatalogDictionary: class OutlineFontFlag(IntFlag): - """ - A class used as an enumerable flag for formatting an outline font - """ + """A class used as an enumerable flag for formatting an outline font""" italic = 1 bold = 2 diff --git a/pypdf/filters.py b/pypdf/filters.py index e3e0a87d0..c3e4d0321 100644 --- a/pypdf/filters.py +++ b/pypdf/filters.py @@ -85,14 +85,18 @@ def decode( """ Decode data which is flate-encoded. - :param data: flate-encoded data. - :param decode_parms: a dictionary of values, understanding the + Args: + data: flate-encoded data. + decode_parms: a dictionary of values, understanding the "/Predictor": key only - :return: the flate-decoded data. - :raises PdfReadError: + Returns: + The flate-decoded data. + + Raises: + PdfReadError: """ - if "decodeParms" in kwargs: # pragma: no cover + if "decodeParms" in kwargs: # deprecated deprecate_with_replacement("decodeParms", "parameters", "4.0.0") decode_parms = kwargs["decodeParms"] str_data = decompress(data) @@ -202,15 +206,22 @@ def decode( **kwargs: Any, ) -> str: """ - :param data: a str sequence of hexadecimal-encoded values to be + Decode an ASCII-Hex encoded data stream. + + Args: + data: a str sequence of hexadecimal-encoded values to be converted into a base-7 ASCII string - :param decode_parms: - :return: a string conversion in base-7 ASCII, where each of its values + decode_parms: a string conversion in base-7 ASCII, where each of its values v is such that 0 <= ord(v) <= 127. - :raises PdfStreamError: + Returns: + A string conversion in base-7 ASCII, where each of its values + v is such that 0 <= ord(v) <= 127. + + Raises: + PdfStreamError: """ - if "decodeParms" in kwargs: # pragma: no cover + if "decodeParms" in kwargs: # deprecated deprecate_with_replacement("decodeParms", "parameters", "4.0.0") decode_parms = kwargs["decodeParms"] # noqa: F841 retval = "" @@ -284,7 +295,8 @@ def decode(self) -> str: http://www.rasip.fer.hr/research/compress/algorithms/fund/lz/lzw.html and the PDFReference - :raises PdfReadError: If the stop code is missing + Raises: + PdfReadError: If the stop code is missing """ cW = self.CLEARDICT baos = "" @@ -324,11 +336,16 @@ def decode( **kwargs: Any, ) -> str: """ - :param data: ``bytes`` or ``str`` text to decode. - :param decode_parms: a dictionary of parameter values. - :return: decoded data. + Decode an LZW encoded data stream. + + Args: + data: bytes`` or ``str`` text to decode. + decode_parms: a dictionary of parameter values. + + Returns: + decoded data. """ - if "decodeParms" in kwargs: # pragma: no cover + if "decodeParms" in kwargs: # deprecated deprecate_with_replacement("decodeParms", "parameters", "4.0.0") decode_parms = kwargs["decodeParms"] # noqa: F841 return LZWDecode.Decoder(data).decode() @@ -343,7 +360,7 @@ def decode( decode_parms: Union[None, ArrayObject, DictionaryObject] = None, **kwargs: Any, ) -> bytes: - if "decodeParms" in kwargs: # pragma: no cover + if "decodeParms" in kwargs: # deprecated deprecate_with_replacement("decodeParms", "parameters", "4.0.0") decode_parms = kwargs["decodeParms"] # noqa: F841 if isinstance(data, str): @@ -376,7 +393,7 @@ def decode( decode_parms: Union[None, ArrayObject, DictionaryObject] = None, **kwargs: Any, ) -> bytes: - if "decodeParms" in kwargs: # pragma: no cover + if "decodeParms" in kwargs: # deprecated deprecate_with_replacement("decodeParms", "parameters", "4.0.0") decode_parms = kwargs["decodeParms"] # noqa: F841 return data @@ -389,7 +406,7 @@ def decode( decode_parms: Union[None, ArrayObject, DictionaryObject] = None, **kwargs: Any, ) -> bytes: - if "decodeParms" in kwargs: # pragma: no cover + if "decodeParms" in kwargs: # deprecated deprecate_with_replacement("decodeParms", "parameters", "4.0.0") decode_parms = kwargs["decodeParms"] # noqa: F841 return data @@ -457,7 +474,7 @@ def decode( height: int = 0, **kwargs: Any, ) -> bytes: - if "decodeParms" in kwargs: # pragma: no cover + if "decodeParms" in kwargs: # deprecated deprecate_with_replacement("decodeParms", "parameters", "4.0.0") decode_parms = kwargs["decodeParms"] parms = CCITTFaxDecode._get_parameters(decode_parms, height) @@ -550,7 +567,7 @@ def decode_stream_data(stream: Any) -> Union[str, bytes]: # utils.StreamObject return data -def decodeStreamData(stream: Any) -> Union[str, bytes]: # pragma: no cover +def decodeStreamData(stream: Any) -> Union[str, bytes]: # deprecated deprecate_with_replacement("decodeStreamData", "decode_stream_data", "4.0.0") return decode_stream_data(stream) @@ -562,7 +579,11 @@ def _xobj_to_image(x_object_obj: Dict[str, Any]) -> Tuple[Optional[str], bytes]: It's unclear if pypdf will keep this function here, hence it's private. It might get removed at any point. - :return: Tuple[file extension, bytes] + Args: + x_object_obj: + + Returns: + Tuple[file extension, bytes] """ try: from PIL import Image diff --git a/pypdf/generic/__init__.py b/pypdf/generic/__init__.py index 5f0b16dd2..984bbf2c2 100644 --- a/pypdf/generic/__init__.py +++ b/pypdf/generic/__init__.py @@ -72,7 +72,7 @@ def readHexStringFromStream( stream: StreamType, -) -> Union["TextStringObject", "ByteStringObject"]: # pragma: no cover +) -> Union["TextStringObject", "ByteStringObject"]: # deprecated deprecate_with_replacement( "readHexStringFromStream", "read_hex_string_from_stream", "4.0.0" ) @@ -82,7 +82,7 @@ def readHexStringFromStream( def readStringFromStream( stream: StreamType, forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, -) -> Union["TextStringObject", "ByteStringObject"]: # pragma: no cover +) -> Union["TextStringObject", "ByteStringObject"]: # deprecated deprecate_with_replacement( "readStringFromStream", "read_string_from_stream", "4.0.0" ) @@ -92,7 +92,7 @@ def readStringFromStream( def createStringObject( string: Union[str, bytes], forced_encoding: Union[None, str, List[str], Dict[int, str]] = None, -) -> Union[TextStringObject, ByteStringObject]: # pragma: no cover +) -> Union[TextStringObject, ByteStringObject]: # deprecated deprecate_with_replacement("createStringObject", "create_string_object", "4.0.0") return create_string_object(string, forced_encoding) diff --git a/pypdf/generic/_annotations.py b/pypdf/generic/_annotations.py index e7a35bf0f..c2f43af90 100644 --- a/pypdf/generic/_annotations.py +++ b/pypdf/generic/_annotations.py @@ -36,11 +36,15 @@ def text( """ Add text annotation. - :param Tuple[int, int, int, int] rect: + Args: + rect: or array of four integers specifying the clickable rectangular area ``[xLL, yLL, xUR, yUR]`` - :param bool open: - :param int flags: + open: + flags: + + Returns: + A dictionary object representing the annotation. """ # TABLE 8.23 Additional entries specific to a text annotation text_obj = DictionaryObject( @@ -70,16 +74,20 @@ def free_text( """ Add text in a rectangle to a page. - :param str text: Text to be added - :param RectangleObject rect: or array of four integers + Args: + text: Text to be added + rect: or array of four integers specifying the clickable rectangular area ``[xLL, yLL, xUR, yUR]`` - :param str font: Name of the Font, e.g. 'Helvetica' - :param bool bold: Print the text in bold - :param bool italic: Print the text in italic - :param str font_size: How big the text will be, e.g. '14pt' - :param str font_color: Hex-string for the color - :param str border_color: Hex-string for the border color - :param str background_color: Hex-string for the background of the annotation + font: Name of the Font, e.g. 'Helvetica' + bold: Print the text in bold + italic: Print the text in italic + font_size: How big the text will be, e.g. '14pt' + font_color: Hex-string for the color + border_color: Hex-string for the border color + background_color: Hex-string for the background of the annotation + + Returns: + A dictionary object representing the annotation. """ font_str = "font: " if bold is True: @@ -124,14 +132,18 @@ def line( """ Draw a line on the PDF. - :param Tuple[float, float] p1: First point - :param Tuple[float, float] p2: Second point - :param RectangleObject rect: or array of four - integers specifying the clickable rectangular area - ``[xLL, yLL, xUR, yUR]`` - :param str text: Text to be displayed as the line annotation - :param str title_bar: Text to be displayed in the title bar of the + Args: + p1: First point + p2: Second point + rect: or array of four + integers specifying the clickable rectangular area + ``[xLL, yLL, xUR, yUR]`` + text: Text to be displayed as the line annotation + title_bar: Text to be displayed in the title bar of the annotation; by convention this is the name of the author + + Returns: + A dictionary object representing the annotation. """ line_obj = DictionaryObject( { @@ -173,9 +185,15 @@ def rectangle( """ Draw a rectangle on the PDF. - :param RectangleObject rect: or array of four - integers specifying the clickable rectangular area - ``[xLL, yLL, xUR, yUR]`` + Args: + rect: or array of four + integers specifying the clickable rectangular area + ``[xLL, yLL, xUR, yUR]`` + rect: + interiour_color: + + Returns: + A dictionary object representing the annotation. """ square_obj = DictionaryObject( { @@ -208,21 +226,24 @@ def link( An external link requires the URL parameter. An internal link requires the target_page_index, fit, and fit args. - - :param RectangleObject rect: or array of four + Args: + rect: or array of four integers specifying the clickable rectangular area ``[xLL, yLL, xUR, yUR]`` - :param border: if provided, an array describing border-drawing + border: if provided, an array describing border-drawing properties. See the PDF spec for details. No border will be drawn if this argument is omitted. - horizontal corner radius, - vertical corner radius, and - border width - Optionally: Dash - :param str url: Link to a website (if you want to make an external link) - :param int target_page_index: index of the page to which the link should go - (if you want to make an internal link) - :param Fit fit: Page fit or 'zoom' option. + url: Link to a website (if you want to make an external link) + target_page_index: index of the page to which the link should go + (if you want to make an internal link) + fit: Page fit or 'zoom' option. + + Returns: + A dictionary object representing the annotation. """ from ..types import BorderArrayType diff --git a/pypdf/generic/_base.py b/pypdf/generic/_base.py index 00b9c17bf..b1adcc557 100644 --- a/pypdf/generic/_base.py +++ b/pypdf/generic/_base.py @@ -80,6 +80,14 @@ def clone( the copy is returned; when force_duplicate == True, a new copy is always performed ignore_fields : list/tuple of Fields names (for dictionaries that will be ignored during cloning (apply also to childs duplication) in standard, clone function call _reference_clone (see _reference) + + Args: + pdf_dest: + force_duplicate: (Default value = False) + ignore_fields: + + Returns: + The cloned PdfObject """ raise Exception("clone PdfObject") @@ -91,6 +99,13 @@ def _reference_clone( indirect_reference attribute exists (which means the objects was already identified in xref/xobjstm) if object has been already referenced do nothing + + Args: + clone: + pdf_dest: + + Returns: + The clone """ try: if clone.indirect_reference.pdf == pdf_dest: @@ -118,7 +133,7 @@ def get_object(self) -> Optional["PdfObject"]: """Resolve indirect references.""" return self - def getObject(self) -> Optional["PdfObject"]: # pragma: no cover + def getObject(self) -> Optional["PdfObject"]: # deprecated deprecation_with_replacement("getObject", "get_object", "3.0.0") return self.get_object() @@ -152,7 +167,7 @@ def read_from_stream(stream: StreamType) -> "NullObject": def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -160,7 +175,7 @@ def __repr__(self) -> str: return "NullObject" @staticmethod - def readFromStream(stream: StreamType) -> "NullObject": # pragma: no cover + def readFromStream(stream: StreamType) -> "NullObject": # deprecated deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0") return NullObject.read_from_stream(stream) @@ -201,7 +216,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -217,7 +232,7 @@ def read_from_stream(stream: StreamType) -> "BooleanObject": raise PdfReadError("Could not read Boolean object") @staticmethod - def readFromStream(stream: StreamType) -> "BooleanObject": # pragma: no cover + def readFromStream(stream: StreamType) -> "BooleanObject": # deprecated deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0") return BooleanObject.read_from_stream(stream) @@ -283,7 +298,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -317,7 +332,7 @@ def read_from_stream(stream: StreamType, pdf: Any) -> "IndirectObject": # PdfRe @staticmethod def readFromStream( stream: StreamType, pdf: Any # PdfReader - ) -> "IndirectObject": # pragma: no cover + ) -> "IndirectObject": # deprecated deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0") return IndirectObject.read_from_stream(stream, pdf) @@ -362,7 +377,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -396,7 +411,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -410,7 +425,7 @@ def read_from_stream(stream: StreamType) -> Union["NumberObject", "FloatObject"] @staticmethod def readFromStream( stream: StreamType, - ) -> Union["NumberObject", "FloatObject"]: # pragma: no cover + ) -> Union["NumberObject", "FloatObject"]: # deprecated deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0") return NumberObject.read_from_stream(stream) @@ -454,7 +469,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -536,7 +551,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -568,7 +583,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -631,7 +646,7 @@ def read_from_stream(stream: StreamType, pdf: Any) -> "NameObject": # PdfReader @staticmethod def readFromStream( stream: StreamType, pdf: Any # PdfReader - ) -> "NameObject": # pragma: no cover + ) -> "NameObject": # deprecated deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0") return NameObject.read_from_stream(stream, pdf) diff --git a/pypdf/generic/_data_structures.py b/pypdf/generic/_data_structures.py index e571dd98a..2b5d65b75 100644 --- a/pypdf/generic/_data_structures.py +++ b/pypdf/generic/_data_structures.py @@ -121,7 +121,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -153,7 +153,7 @@ def read_from_stream( @staticmethod def readFromStream( stream: StreamType, pdf: Any # PdfReader - ) -> "ArrayObject": # pragma: no cover + ) -> "ArrayObject": # deprecated deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0") return ArrayObject.read_from_stream(stream, pdf) @@ -188,7 +188,15 @@ def _clone( force_duplicate: bool, ignore_fields: Union[Tuple[str, ...], List[str]], ) -> None: - """update the object from src""" + """ + Update the object from src + + Args: + src: "DictionaryObject": + pdf_dest: + force_duplicate: + ignore_fields: + """ # First check if this is a chain list, we need to loop to prevent recur if ( ("/Next" not in ignore_fields and "/Next" in src) @@ -272,9 +280,12 @@ def xmp_metadata(self) -> Optional[PdfObject]: this object, if available. Stability: Added in v1.12, will exist for all future v1.x releases. - @return Returns a {@link #xmp.XmpInformation XmlInformation} instance - that can be used to access XMP metadata from the document. Can also - return None if no metadata was found on the document root. + + Returns: + Returns a {@link #xmp.XmpInformation XmlInformation} instance + that can be used to access XMP metadata from the document. Can also + return None if no metadata was found on the document root. + """ from ..xmp import XmpInformation @@ -290,7 +301,7 @@ def xmp_metadata(self) -> Optional[PdfObject]: def getXmpMetadata( self, - ) -> Optional[PdfObject]: # pragma: no cover + ) -> Optional[PdfObject]: # deprecated """ .. deprecated:: 1.28.3 @@ -300,7 +311,7 @@ def getXmpMetadata( return self.xmp_metadata @property - def xmpMetadata(self) -> Optional[PdfObject]: # pragma: no cover + def xmpMetadata(self) -> Optional[PdfObject]: # deprecated """ .. deprecated:: 1.28.3 @@ -322,7 +333,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("writeToStream", "write_to_stream", "3.0.0") self.write_to_stream(stream, encryption_key) @@ -465,7 +476,7 @@ def read_unsized_from_steam(stream: StreamType, pdf: Any) -> bytes: # PdfReader @staticmethod def readFromStream( stream: StreamType, pdf: Any # PdfReader - ) -> "DictionaryObject": # pragma: no cover + ) -> "DictionaryObject": # deprecated deprecation_with_replacement("readFromStream", "read_from_stream", "3.0.0") return DictionaryObject.read_from_stream(stream, pdf) @@ -474,7 +485,7 @@ class TreeObject(DictionaryObject): def __init__(self) -> None: DictionaryObject.__init__(self) - def hasChildren(self) -> bool: # pragma: no cover + def hasChildren(self) -> bool: # deprecated deprecate_with_replacement("hasChildren", "has_children", "4.0.0") return self.has_children() @@ -499,7 +510,7 @@ def children(self) -> Iterable[Any]: return child = child_ref.get_object() - def addChild(self, child: Any, pdf: Any) -> None: # pragma: no cover + def addChild(self, child: Any, pdf: Any) -> None: # deprecated deprecation_with_replacement("addChild", "add_child", "3.0.0") self.add_child(child, pdf) @@ -561,14 +572,22 @@ def inc_parent_counter( child_obj[NameObject("/Parent")] = self.indirect_reference inc_parent_counter(self, child_obj.get("/Count", 1)) - def removeChild(self, child: Any) -> None: # pragma: no cover + def removeChild(self, child: Any) -> None: # deprecated deprecation_with_replacement("removeChild", "remove_child", "3.0.0") self.remove_child(child) def _remove_node_from_tree( self, prev: Any, prev_ref: Any, cur: Any, last: Any ) -> None: - """Adjust the pointers of the linked list and tree node count.""" + """ + Adjust the pointers of the linked list and tree node count. + + Args: + prev: + prev_ref: + cur: + last: + """ next_ref = cur.get(NameObject("/Next"), None) if prev is None: if next_ref: @@ -646,7 +665,7 @@ def remove_from_tree(self) -> None: else: cast("TreeObject", self["/Parent"]).remove_child(self) - def emptyTree(self) -> None: # pragma: no cover + def emptyTree(self) -> None: # deprecated deprecate_with_replacement("emptyTree", "empty_tree", "4.0.0") self.empty_tree() @@ -668,6 +687,9 @@ def _reset_node_tree_relationship(child_obj: Any) -> None: Call this after a node has been removed from a tree. This resets the nodes attributes in respect to that tree. + + Args: + child_obj: """ del child_obj[NameObject("/Parent")] if NameObject("/Next") in child_obj: @@ -688,7 +710,15 @@ def _clone( force_duplicate: bool, ignore_fields: Union[Tuple[str, ...], List[str]], ) -> None: - """update the object from src""" + """ + Update the object from src. + + Args: + src: + pdf_dest: + force_duplicate: + ignore_fields: + """ self._data = cast("StreamObject", src)._data try: decoded_self = cast("StreamObject", src).decoded_self @@ -707,12 +737,12 @@ def hash_value_data(self) -> bytes: return data @property - def decodedSelf(self) -> Optional["DecodedStreamObject"]: # pragma: no cover + def decodedSelf(self) -> Optional["DecodedStreamObject"]: # deprecated deprecation_with_replacement("decodedSelf", "decoded_self", "3.0.0") return self.decoded_self @decodedSelf.setter - def decodedSelf(self, value: "DecodedStreamObject") -> None: # pragma: no cover + def decodedSelf(self, value: "DecodedStreamObject") -> None: # deprecated deprecation_with_replacement("decodedSelf", "decoded_self", "3.0.0") self.decoded_self = value @@ -742,7 +772,7 @@ def write_to_stream( @staticmethod def initializeFromDictionary( data: Dict[str, Any] - ) -> Union["EncodedStreamObject", "DecodedStreamObject"]: # pragma: no cover + ) -> Union["EncodedStreamObject", "DecodedStreamObject"]: # deprecated return StreamObject.initialize_from_dictionary(data) @staticmethod @@ -760,7 +790,7 @@ def initialize_from_dictionary( retval.update(data) return retval - def flateEncode(self) -> "EncodedStreamObject": # pragma: no cover + def flateEncode(self) -> "EncodedStreamObject": # deprecated deprecation_with_replacement("flateEncode", "flate_encode", "3.0.0") return self.flate_encode() @@ -791,11 +821,11 @@ def get_data(self) -> Any: def set_data(self, data: Any) -> Any: self._data = data - def getData(self) -> Any: # pragma: no cover + def getData(self) -> Any: # deprecated deprecation_with_replacement("getData", "get_data", "3.0.0") return self._data - def setData(self, data: Any) -> None: # pragma: no cover + def setData(self, data: Any) -> None: # deprecated deprecation_with_replacement("setData", "set_data", "3.0.0") self.set_data(data) @@ -805,12 +835,12 @@ def __init__(self) -> None: self.decoded_self: Optional["DecodedStreamObject"] = None @property - def decodedSelf(self) -> Optional["DecodedStreamObject"]: # pragma: no cover + def decodedSelf(self) -> Optional["DecodedStreamObject"]: # deprecated deprecation_with_replacement("decodedSelf", "decoded_self", "3.0.0") return self.decoded_self @decodedSelf.setter - def decodedSelf(self, value: DecodedStreamObject) -> None: # pragma: no cover + def decodedSelf(self, value: DecodedStreamObject) -> None: # deprecated deprecation_with_replacement("decodedSelf", "decoded_self", "3.0.0") self.decoded_self = value @@ -831,14 +861,14 @@ def get_data(self) -> Union[None, str, bytes]: self.decoded_self = decoded return decoded._data - def getData(self) -> Union[None, str, bytes]: # pragma: no cover + def getData(self) -> Union[None, str, bytes]: # deprecated deprecation_with_replacement("getData", "get_data", "3.0.0") return self.get_data() - def set_data(self, data: Any) -> None: # pragma: no cover + def set_data(self, data: Any) -> None: # deprecated raise PdfReadError("Creating EncodedStreamObject is not currently supported") - def setData(self, data: Any) -> None: # pragma: no cover + def setData(self, data: Any) -> None: # deprecated deprecation_with_replacement("setData", "set_data", "3.0.0") return self.set_data(data) @@ -882,7 +912,17 @@ def clone( force_duplicate: bool = False, ignore_fields: Union[Tuple[str, ...], List[str], None] = (), ) -> "ContentStream": - """clone object into pdf_dest""" + """ + Clone object into pdf_dest. + + Args: + pdf_dest: + force_duplicate: + ignore_fields: + + Returns: + The cloned ContentStream + """ try: if self.indirect_reference.pdf == pdf_dest and not force_duplicate: # type: ignore return self @@ -904,7 +944,15 @@ def _clone( force_duplicate: bool, ignore_fields: Union[Tuple[str, ...], List[str]], ) -> None: - """update the object from src""" + """ + Update the object from src. + + Args: + src: + pdf_dest: + force_duplicate: + ignore_fields: + """ self.pdf = pdf_dest self.operations = list(cast("ContentStream", src).operations) self.forced_encoding = cast("ContentStream", src).forced_encoding @@ -1109,7 +1157,7 @@ def field_type(self) -> Optional[NameObject]: return self.get(FieldDictionaryAttributes.FT) @property - def fieldType(self) -> Optional[NameObject]: # pragma: no cover + def fieldType(self) -> Optional[NameObject]: # deprecated """ .. deprecated:: 1.28.3 @@ -1139,7 +1187,7 @@ def alternate_name(self) -> Optional[str]: return self.get(FieldDictionaryAttributes.TU) @property - def altName(self) -> Optional[str]: # pragma: no cover + def altName(self) -> Optional[str]: # deprecated """ .. deprecated:: 1.28.3 @@ -1158,7 +1206,7 @@ def mapping_name(self) -> Optional[str]: return self.get(FieldDictionaryAttributes.TM) @property - def mappingName(self) -> Optional[str]: # pragma: no cover + def mappingName(self) -> Optional[str]: # deprecated """ .. deprecated:: 1.28.3 @@ -1189,7 +1237,7 @@ def default_value(self) -> Optional[Any]: return self.get(FieldDictionaryAttributes.DV) @property - def defaultValue(self) -> Optional[Any]: # pragma: no cover + def defaultValue(self) -> Optional[Any]: # deprecated """ .. deprecated:: 1.28.3 @@ -1208,7 +1256,7 @@ def additional_actions(self) -> Optional[DictionaryObject]: return self.get(FieldDictionaryAttributes.AA) @property - def additionalActions(self) -> Optional[DictionaryObject]: # pragma: no cover + def additionalActions(self) -> Optional[DictionaryObject]: # deprecated """ .. deprecated:: 1.28.3 @@ -1223,12 +1271,14 @@ class Destination(TreeObject): A class representing a destination within a PDF file. See section 8.2.1 of the PDF 1.6 reference. - :param str title: Title of this destination. - :param IndirectObject page: Reference to the page of this destination. Should + Args: + title: Title of this destination. + page: Reference to the page of this destination. Should be an instance of :class:`IndirectObject`. - :param Fit fit: How the destination is displayed. - :raises PdfReadError: If destination type is invalid. + fit: How the destination is displayed. + Raises: + PdfReadError: If destination type is invalid. """ @@ -1291,7 +1341,7 @@ def dest_array(self) -> "ArrayObject": ] ) - def getDestArray(self) -> "ArrayObject": # pragma: no cover + def getDestArray(self) -> "ArrayObject": # deprecated """ .. deprecated:: 1.28.3 diff --git a/pypdf/generic/_fit.py b/pypdf/generic/_fit.py index b0e7aaa91..0522b8d57 100644 --- a/pypdf/generic/_fit.py +++ b/pypdf/generic/_fit.py @@ -29,6 +29,14 @@ def xyz( that the current value of that parameter is to be retained unchanged. A zoom value of 0 has the same meaning as a null value. + + Args: + left: (Default value = None) + top: (Default value = None) + zoom: (Default value = None) + + Returns: + The created fit object. """ return Fit(fit_type="/XYZ", fit_args=(left, top, zoom)) @@ -53,6 +61,12 @@ def fit_horizontally(cls, top: Optional[float] = None) -> "Fit": A null value for `top` specifies that the current value of that parameter is to be retained unchanged. + + Args: + top: (Default value = None) + + Returns: + The created fit object. """ return Fit(fit_type="/FitH", fit_args=(top,)) @@ -80,6 +94,15 @@ def fit_rectangle( A null value for any of the parameters may result in unpredictable behavior. + + Args: + left: (Default value = None) + bottom: (Default value = None) + right: (Default value = None) + top: (Default value = None) + + Returns: + The created fit object. """ return Fit(fit_type="/FitR", fit_args=(left, bottom, right, top)) @@ -104,6 +127,12 @@ def fit_box_horizontally(cls, top: Optional[float] = None) -> "Fit": A null value for top specifies that the current value of that parameter is to be retained unchanged. + + Args: + top: (Default value = None) + + Returns: + The created fit object. """ return Fit(fit_type="/FitBH", fit_args=(top,)) @@ -117,6 +146,12 @@ def fit_box_vertically(cls, left: Optional[float] = None) -> "Fit": A null value for left specifies that the current value of that parameter is to be retained unchanged. + + Args: + left: (Default value = None) + + Returns: + The created fit object. """ return Fit(fit_type="/FitBV", fit_args=(left,)) diff --git a/pypdf/generic/_outline.py b/pypdf/generic/_outline.py index c2e72c0ab..dcff76d6e 100644 --- a/pypdf/generic/_outline.py +++ b/pypdf/generic/_outline.py @@ -29,7 +29,7 @@ def write_to_stream( stream.write(b">>") -class Bookmark(OutlineItem): # pragma: no cover +class Bookmark(OutlineItem): # deprecated def __init__(self, *args: Any, **kwargs: Any) -> None: deprecation_with_replacement("Bookmark", "OutlineItem", "3.0.0") super().__init__(*args, **kwargs) diff --git a/pypdf/generic/_rectangle.py b/pypdf/generic/_rectangle.py index ce9876cd2..786b88ebd 100644 --- a/pypdf/generic/_rectangle.py +++ b/pypdf/generic/_rectangle.py @@ -41,7 +41,7 @@ def scale(self, sx: float, sy: float) -> "RectangleObject": def ensureIsNumber( self, value: Any - ) -> Union[FloatObject, NumberObject]: # pragma: no cover + ) -> Union[FloatObject, NumberObject]: # deprecated deprecation_no_replacement("ensureIsNumber", "3.0.0") return self._ensure_is_number(value) @@ -80,35 +80,35 @@ def top(self) -> FloatObject: def top(self, f: float) -> None: self[3] = FloatObject(f) - def getLowerLeft_x(self) -> FloatObject: # pragma: no cover + def getLowerLeft_x(self) -> FloatObject: # deprecated deprecation_with_replacement("getLowerLeft_x", "left", "3.0.0") return self.left - def getLowerLeft_y(self) -> FloatObject: # pragma: no cover + def getLowerLeft_y(self) -> FloatObject: # deprecated deprecation_with_replacement("getLowerLeft_y", "bottom", "3.0.0") return self.bottom - def getUpperRight_x(self) -> FloatObject: # pragma: no cover + def getUpperRight_x(self) -> FloatObject: # deprecated deprecation_with_replacement("getUpperRight_x", "right", "3.0.0") return self.right - def getUpperRight_y(self) -> FloatObject: # pragma: no cover + def getUpperRight_y(self) -> FloatObject: # deprecated deprecation_with_replacement("getUpperRight_y", "top", "3.0.0") return self.top - def getUpperLeft_x(self) -> FloatObject: # pragma: no cover + def getUpperLeft_x(self) -> FloatObject: # deprecated deprecation_with_replacement("getUpperLeft_x", "left", "3.0.0") return self.left - def getUpperLeft_y(self) -> FloatObject: # pragma: no cover + def getUpperLeft_y(self) -> FloatObject: # deprecated deprecation_with_replacement("getUpperLeft_y", "top", "3.0.0") return self.top - def getLowerRight_x(self) -> FloatObject: # pragma: no cover + def getLowerRight_x(self) -> FloatObject: # deprecated deprecation_with_replacement("getLowerRight_x", "right", "3.0.0") return self.right - def getLowerRight_y(self) -> FloatObject: # pragma: no cover + def getLowerRight_y(self) -> FloatObject: # deprecated deprecation_with_replacement("getLowerRight_y", "bottom", "3.0.0") return self.bottom @@ -162,41 +162,41 @@ def upper_right(self, value: List[Any]) -> None: def getLowerLeft( self, - ) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover + ) -> Tuple[decimal.Decimal, decimal.Decimal]: # deprecated deprecation_with_replacement("getLowerLeft", "lower_left", "3.0.0") return self.lower_left def getLowerRight( self, - ) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover + ) -> Tuple[decimal.Decimal, decimal.Decimal]: # deprecated deprecation_with_replacement("getLowerRight", "lower_right", "3.0.0") return self.lower_right def getUpperLeft( self, - ) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover + ) -> Tuple[decimal.Decimal, decimal.Decimal]: # deprecated deprecation_with_replacement("getUpperLeft", "upper_left", "3.0.0") return self.upper_left def getUpperRight( self, - ) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover + ) -> Tuple[decimal.Decimal, decimal.Decimal]: # deprecated deprecation_with_replacement("getUpperRight", "upper_right", "3.0.0") return self.upper_right - def setLowerLeft(self, value: Tuple[float, float]) -> None: # pragma: no cover + def setLowerLeft(self, value: Tuple[float, float]) -> None: # deprecated deprecation_with_replacement("setLowerLeft", "lower_left", "3.0.0") self.lower_left = value # type: ignore - def setLowerRight(self, value: Tuple[float, float]) -> None: # pragma: no cover + def setLowerRight(self, value: Tuple[float, float]) -> None: # deprecated deprecation_with_replacement("setLowerRight", "lower_right", "3.0.0") self[2], self[1] = (self._ensure_is_number(x) for x in value) - def setUpperLeft(self, value: Tuple[float, float]) -> None: # pragma: no cover + def setUpperLeft(self, value: Tuple[float, float]) -> None: # deprecated deprecation_with_replacement("setUpperLeft", "upper_left", "3.0.0") self[0], self[3] = (self._ensure_is_number(x) for x in value) - def setUpperRight(self, value: Tuple[float, float]) -> None: # pragma: no cover + def setUpperRight(self, value: Tuple[float, float]) -> None: # deprecated deprecation_with_replacement("setUpperRight", "upper_right", "3.0.0") self[2], self[3] = (self._ensure_is_number(x) for x in value) @@ -204,7 +204,7 @@ def setUpperRight(self, value: Tuple[float, float]) -> None: # pragma: no cover def width(self) -> decimal.Decimal: return self.right - self.left - def getWidth(self) -> decimal.Decimal: # pragma: no cover + def getWidth(self) -> decimal.Decimal: # deprecated deprecation_with_replacement("getWidth", "width", "3.0.0") return self.width @@ -212,54 +212,54 @@ def getWidth(self) -> decimal.Decimal: # pragma: no cover def height(self) -> decimal.Decimal: return self.top - self.bottom - def getHeight(self) -> decimal.Decimal: # pragma: no cover + def getHeight(self) -> decimal.Decimal: # deprecated deprecation_with_replacement("getHeight", "height", "3.0.0") return self.height @property - def lowerLeft(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover + def lowerLeft(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # deprecated deprecation_with_replacement("lowerLeft", "lower_left", "3.0.0") return self.lower_left @lowerLeft.setter def lowerLeft( self, value: Tuple[decimal.Decimal, decimal.Decimal] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("lowerLeft", "lower_left", "3.0.0") self.lower_left = value @property - def lowerRight(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover + def lowerRight(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # deprecated deprecation_with_replacement("lowerRight", "lower_right", "3.0.0") return self.lower_right @lowerRight.setter def lowerRight( self, value: Tuple[decimal.Decimal, decimal.Decimal] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("lowerRight", "lower_right", "3.0.0") self.lower_right = value @property - def upperLeft(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover + def upperLeft(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # deprecated deprecation_with_replacement("upperLeft", "upper_left", "3.0.0") return self.upper_left @upperLeft.setter def upperLeft( self, value: Tuple[decimal.Decimal, decimal.Decimal] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("upperLeft", "upper_left", "3.0.0") self.upper_left = value @property - def upperRight(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # pragma: no cover + def upperRight(self) -> Tuple[decimal.Decimal, decimal.Decimal]: # deprecated deprecation_with_replacement("upperRight", "upper_right", "3.0.0") return self.upper_right @upperRight.setter def upperRight( self, value: Tuple[decimal.Decimal, decimal.Decimal] - ) -> None: # pragma: no cover + ) -> None: # deprecated deprecation_with_replacement("upperRight", "upper_right", "3.0.0") self.upper_right = value diff --git a/pypdf/generic/_utils.py b/pypdf/generic/_utils.py index 2f8debdce..ed1fd1f5d 100644 --- a/pypdf/generic/_utils.py +++ b/pypdf/generic/_utils.py @@ -117,9 +117,16 @@ def create_string_object( """ Create a ByteStringObject or a TextStringObject from a string to represent the string. - :param Union[str, bytes] string: A string + Args: + string: + forced_encoding: + + Returns: + A ByteStringObject + + Raises: + TypeError: If string is not of type str or bytes. - :raises TypeError: If string is not of type str or bytes. """ if isinstance(string, str): return TextStringObject(string) diff --git a/pypdf/pagerange.py b/pypdf/pagerange.py index c7fe2ada4..7c6061f28 100644 --- a/pypdf/pagerange.py +++ b/pypdf/pagerange.py @@ -78,7 +78,15 @@ def __init__(self, arg: Union[slice, "PageRange", str]) -> None: @staticmethod def valid(input: Any) -> bool: - """True if input is a valid initializer for a PageRange.""" + """ + True if input is a valid initializer for a PageRange. + + Args: + input: A possible PageRange string or a PageRange object. + + Returns: + True, if the ``input`` is a valid PageRange. + """ return isinstance(input, (slice, PageRange)) or ( isinstance(input, str) and bool(re.match(PAGE_RANGE_RE, input)) ) @@ -106,9 +114,16 @@ def __repr__(self) -> str: def indices(self, n: int) -> Tuple[int, int, int]: """ - n is the length of the list of pages to choose from. + Assuming a sequence of length n, calculate the start and stop + indices, and the stride length of the PageRange. - Returns arguments for range(). See help(slice.indices). + See help(slice.indices). + + Args: + n: the length of the list of pages to choose from. + + Returns: + Arguments for range() """ return self._slice.indices(n) @@ -144,9 +159,13 @@ def parse_filename_page_ranges( """ Given a list of filenames and page ranges, return a list of (filename, page_range) pairs. - First arg must be a filename; other ags are filenames, page-range - expressions, slice objects, or PageRange objects. - A filename not followed by a page range indicates all pages of the file. + Args: + args: A list where the first element is a filename. The other elements are + filenames, page-range expressions, slice objects, or PageRange objects. + A filename not followed by a page range indicates all pages of the file. + + Returns: + A list of (filename, page_range) pairs. """ pairs: List[Tuple[str, PageRange]] = [] pdf_filename = None diff --git a/pypdf/xmp.py b/pypdf/xmp.py index 296315dd5..aaae96a2b 100644 --- a/pypdf/xmp.py +++ b/pypdf/xmp.py @@ -213,7 +213,9 @@ class XmpInformation(PdfObject): An object that represents Adobe XMP metadata. Usually accessed by :py:attr:`xmp_metadata()` - :raises PdfReadError: if XML is invalid + Raises: + PdfReadError: if XML is invalid + """ def __init__(self, stream: ContentStream) -> None: @@ -229,7 +231,7 @@ def __init__(self, stream: ContentStream) -> None: self.cache: Dict[Any, Any] = {} @property - def rdfRoot(self) -> XmlElement: # pragma: no cover + def rdfRoot(self) -> XmlElement: # deprecated deprecate_with_replacement("rdfRoot", "rdf_root", "4.0.0") return self.rdf_root @@ -240,7 +242,7 @@ def write_to_stream( def writeToStream( self, stream: StreamType, encryption_key: Union[None, str, bytes] - ) -> None: # pragma: no cover + ) -> None: # deprecated """ .. deprecated:: 1.28.0 @@ -259,7 +261,7 @@ def get_element(self, about_uri: str, namespace: str, name: str) -> Iterator[Any def getElement( self, aboutUri: str, namespace: str, name: str - ) -> Iterator[Any]: # pragma: no cover + ) -> Iterator[Any]: # deprecated """ .. deprecated:: 1.28.0 @@ -281,7 +283,7 @@ def get_nodes_in_namespace(self, about_uri: str, namespace: str) -> Iterator[Any def getNodesInNamespace( self, aboutUri: str, namespace: str - ) -> Iterator[Any]: # pragma: no cover + ) -> Iterator[Any]: # deprecated """ .. deprecated:: 1.28.0 @@ -405,12 +407,12 @@ def _get_text(self, element: XmlElement) -> str: """ @property - def xmp_createDate(self) -> datetime.datetime: # pragma: no cover + def xmp_createDate(self) -> datetime.datetime: # deprecated deprecate_with_replacement("xmp_createDate", "xmp_create_date", "4.0.0") return self.xmp_create_date @xmp_createDate.setter - def xmp_createDate(self, value: datetime.datetime) -> None: # pragma: no cover + def xmp_createDate(self, value: datetime.datetime) -> None: # deprecated deprecate_with_replacement("xmp_createDate", "xmp_create_date", "4.0.0") self.xmp_create_date = value @@ -423,12 +425,12 @@ def xmp_createDate(self, value: datetime.datetime) -> None: # pragma: no cover """ @property - def xmp_modifyDate(self) -> datetime.datetime: # pragma: no cover + def xmp_modifyDate(self) -> datetime.datetime: # deprecated deprecate_with_replacement("xmp_modifyDate", "xmp_modify_date", "4.0.0") return self.xmp_modify_date @xmp_modifyDate.setter - def xmp_modifyDate(self, value: datetime.datetime) -> None: # pragma: no cover + def xmp_modifyDate(self, value: datetime.datetime) -> None: # deprecated deprecate_with_replacement("xmp_modifyDate", "xmp_modify_date", "4.0.0") self.xmp_modify_date = value @@ -442,12 +444,12 @@ def xmp_modifyDate(self, value: datetime.datetime) -> None: # pragma: no cover """ @property - def xmp_metadataDate(self) -> datetime.datetime: # pragma: no cover + def xmp_metadataDate(self) -> datetime.datetime: # deprecated deprecate_with_replacement("xmp_metadataDate", "xmp_metadata_date", "4.0.0") return self.xmp_metadata_date @xmp_metadataDate.setter - def xmp_metadataDate(self, value: datetime.datetime) -> None: # pragma: no cover + def xmp_metadataDate(self, value: datetime.datetime) -> None: # deprecated deprecate_with_replacement("xmp_metadataDate", "xmp_metadata_date", "4.0.0") self.xmp_metadata_date = value @@ -455,12 +457,12 @@ def xmp_metadataDate(self, value: datetime.datetime) -> None: # pragma: no cove """The name of the first known tool used to create the resource.""" @property - def xmp_creatorTool(self) -> str: # pragma: no cover + def xmp_creatorTool(self) -> str: # deprecated deprecation_with_replacement("xmp_creatorTool", "xmp_creator_tool", "3.0.0") return self.xmp_creator_tool @xmp_creatorTool.setter - def xmp_creatorTool(self, value: str) -> None: # pragma: no cover + def xmp_creatorTool(self, value: str) -> None: # deprecated deprecation_with_replacement("xmp_creatorTool", "xmp_creator_tool", "3.0.0") self.xmp_creator_tool = value @@ -470,12 +472,12 @@ def xmp_creatorTool(self, value: str) -> None: # pragma: no cover """ @property - def xmpmm_documentId(self) -> str: # pragma: no cover + def xmpmm_documentId(self) -> str: # deprecated deprecation_with_replacement("xmpmm_documentId", "xmpmm_document_id", "3.0.0") return self.xmpmm_document_id @xmpmm_documentId.setter - def xmpmm_documentId(self, value: str) -> None: # pragma: no cover + def xmpmm_documentId(self, value: str) -> None: # deprecated deprecation_with_replacement("xmpmm_documentId", "xmpmm_document_id", "3.0.0") self.xmpmm_document_id = value @@ -486,12 +488,12 @@ def xmpmm_documentId(self, value: str) -> None: # pragma: no cover """ @property - def xmpmm_instanceId(self) -> str: # pragma: no cover + def xmpmm_instanceId(self) -> str: # deprecated deprecation_with_replacement("xmpmm_instanceId", "xmpmm_instance_id", "3.0.0") return cast(str, self.xmpmm_instance_id) @xmpmm_instanceId.setter - def xmpmm_instanceId(self, value: str) -> None: # pragma: no cover + def xmpmm_instanceId(self, value: str) -> None: # deprecated deprecation_with_replacement("xmpmm_instanceId", "xmpmm_instance_id", "3.0.0") self.xmpmm_instance_id = value @@ -501,7 +503,8 @@ def custom_properties(self) -> Dict[Any, Any]: Retrieve custom metadata properties defined in the undocumented pdfx metadata schema. - :return: a dictionary of key/value items for custom metadata properties. + Returns: + A dictionary of key/value items for custom metadata properties. """ if not hasattr(self, "_custom_properties"): self._custom_properties = {}