Source code for pdftools_sdk.pdf.document

from __future__ import annotations
import io
from typing import List, Iterator, Tuple, Optional, Any, TYPE_CHECKING, Callable
from ctypes import *
from datetime import datetime
from numbers import Number
from pdftools_sdk.internal import _lib
from pdftools_sdk.internal.utils import _string_to_utf16, _utf16_to_string
from pdftools_sdk.internal.streams import _StreamDescriptor, _NativeStream
from pdftools_sdk.internal.native_base import _NativeBase
from pdftools_sdk.internal.native_object import _NativeObject

import pdftools_sdk.internal

if TYPE_CHECKING:
    from pdftools_sdk.pdf.conformance import Conformance
    from pdftools_sdk.pdf.permission import Permission
    from pdftools_sdk.pdf.signature_field_list import SignatureFieldList
    from pdftools_sdk.pdf.xfa_type import XfaType
    from pdftools_sdk.pdf.metadata import Metadata

else:
    Conformance = "pdftools_sdk.pdf.conformance.Conformance"
    Permission = "pdftools_sdk.pdf.permission.Permission"
    SignatureFieldList = "pdftools_sdk.pdf.signature_field_list.SignatureFieldList"
    XfaType = "pdftools_sdk.pdf.xfa_type.XfaType"
    Metadata = "pdftools_sdk.pdf.metadata.Metadata"


[docs] class Document(_NativeObject): """ The PDF document PDF documents are either opened using :meth:`pdftools_sdk.pdf.document.Document.open` or the result of an operation, e.g. of PDF optimization (see :meth:`pdftools_sdk.optimization.optimizer.Optimizer.optimize_document` ). """
[docs] @staticmethod def open(stream: io.IOBase, password: Optional[str] = None) -> Document: """ Open a PDF document. Documents opened with this method are read-only and cannot be modified. Args: stream (io.IOBase): The stream from which the PDF is read. password (Optional[str]): The password to open the PDF document. If `None` or empty, no password is used. Returns: pdftools_sdk.pdf.document.Document: The newly created document instance Raises: pdftools_sdk.license_error.LicenseError: The license check has failed. pdftools_sdk.password_error.PasswordError: The document is encrypted and the `password` is invalid. pdftools_sdk.corrupt_error.CorruptError: The document is corrupt or not a PDF. pdftools_sdk.unsupported_feature_error.UnsupportedFeatureError: The document is an unencrypted wrapper document. pdftools_sdk.generic_error.GenericError: A generic error occurred. """ if not isinstance(stream, io.IOBase): raise TypeError(f"Expected type {io.IOBase.__name__}, but got {type(stream).__name__}.") if password is not None and not isinstance(password, str): raise TypeError(f"Expected type {str.__name__} or None, but got {type(password).__name__}.") _lib.PdfToolsPdf_Document_OpenW.argtypes = [POINTER(pdftools_sdk.internal.streams._StreamDescriptor), c_wchar_p] _lib.PdfToolsPdf_Document_OpenW.restype = c_void_p ret_val = _lib.PdfToolsPdf_Document_OpenW(_StreamDescriptor(stream), _string_to_utf16(password)) if ret_val is None: _NativeBase._throw_last_error(False) return Document._create_dynamic_type(ret_val)
@property def conformance(self) -> Optional[Conformance]: """ The claimed conformance of the document This method only returns the claimed conformance level, the document is not validated. This property can return `None` if the document's conformance is unknown. Returns: Optional[pdftools_sdk.pdf.conformance.Conformance] """ from pdftools_sdk.pdf.conformance import Conformance _lib.PdfToolsPdf_Document_GetConformance.argtypes = [c_void_p, POINTER(c_int)] _lib.PdfToolsPdf_Document_GetConformance.restype = c_bool ret_val = c_int() if not _lib.PdfToolsPdf_Document_GetConformance(self._handle, byref(ret_val)): _NativeBase._throw_last_error() return None return Conformance(ret_val.value) @property def page_count(self) -> int: """ The number of pages in the document If the document is a collection (also known as PDF Portfolio), then this property is `0`. Returns: int """ _lib.PdfToolsPdf_Document_GetPageCount.argtypes = [c_void_p] _lib.PdfToolsPdf_Document_GetPageCount.restype = c_int ret_val = _lib.PdfToolsPdf_Document_GetPageCount(self._handle) if ret_val == -1: _NativeBase._throw_last_error() return ret_val @property def permissions(self) -> Optional[Permission]: """ The access permissions applicable for this document This property is `None`, if the document is not encrypted. Note that these permissions might be different from the "Document Restrictions Summary" displayed in Adobe Acrobat. This is because Acrobat's restrictions are also affected by other factors. For example, "Document Assembly" is generally only allowed in Acrobat Pro and not the Acrobat Reader. Returns: Optional[pdftools_sdk.pdf.permission.Permission] """ from pdftools_sdk.pdf.permission import Permission _lib.PdfToolsPdf_Document_GetPermissions.argtypes = [c_void_p, POINTER(c_int)] _lib.PdfToolsPdf_Document_GetPermissions.restype = c_bool ret_val = c_int() if not _lib.PdfToolsPdf_Document_GetPermissions(self._handle, byref(ret_val)): _NativeBase._throw_last_error() return None return Permission(ret_val.value) @property def is_linearized(self) -> bool: """ Whether the document is linearized Returns: bool """ _lib.PdfToolsPdf_Document_IsLinearized.argtypes = [c_void_p] _lib.PdfToolsPdf_Document_IsLinearized.restype = c_bool ret_val = _lib.PdfToolsPdf_Document_IsLinearized(self._handle) if not ret_val: _NativeBase._throw_last_error() return ret_val @property def is_signed(self) -> bool: """ Returns: bool """ _lib.PdfToolsPdf_Document_IsSigned.argtypes = [c_void_p] _lib.PdfToolsPdf_Document_IsSigned.restype = c_bool ret_val = _lib.PdfToolsPdf_Document_IsSigned(self._handle) if not ret_val: _NativeBase._throw_last_error() return ret_val @property def signature_fields(self) -> SignatureFieldList: """ Returns: pdftools_sdk.pdf.signature_field_list.SignatureFieldList """ from pdftools_sdk.pdf.signature_field_list import SignatureFieldList _lib.PdfToolsPdf_Document_GetSignatureFields.argtypes = [c_void_p] _lib.PdfToolsPdf_Document_GetSignatureFields.restype = c_void_p ret_val = _lib.PdfToolsPdf_Document_GetSignatureFields(self._handle) if ret_val is None: _NativeBase._throw_last_error(False) return SignatureFieldList._create_dynamic_type(ret_val) @property def xfa(self) -> XfaType: """ Whether the document is an XML Forms Architecture (XFA) or a PDF document While XFA documents may seem like regular PDF documents they are not and cannot be processed by many components (error :class:`pdftools_sdk.unsupported_feature_error.UnsupportedFeatureError` ). An XFA form is included as a resource in a mere shell PDF. The PDF pages' content is generated dynamically from the XFA data, which is a complex, non-standardized process. For this reason, XFA is forbidden by the ISO Standards ISO 19'005-2 (PDF/A-2) and ISO 32'000-2 (PDF 2.0) and newer. It is recommended to convert XFA documents to PDF using an Adobe product, e.g. by using the "Print to PDF" function of Adobe Acrobat Reader. Returns: pdftools_sdk.pdf.xfa_type.XfaType """ from pdftools_sdk.pdf.xfa_type import XfaType _lib.PdfToolsPdf_Document_GetXfa.argtypes = [c_void_p] _lib.PdfToolsPdf_Document_GetXfa.restype = c_int ret_val = _lib.PdfToolsPdf_Document_GetXfa(self._handle) if ret_val == 0: _NativeBase._throw_last_error() return XfaType(ret_val) @property def metadata(self) -> Metadata: """ The metadata of the document. Returns: pdftools_sdk.pdf.metadata.Metadata """ from pdftools_sdk.pdf.metadata import Metadata _lib.PdfToolsPdf_Document_GetMetadata.argtypes = [c_void_p] _lib.PdfToolsPdf_Document_GetMetadata.restype = c_void_p ret_val = _lib.PdfToolsPdf_Document_GetMetadata(self._handle) if ret_val is None: _NativeBase._throw_last_error(False) return Metadata._create_dynamic_type(ret_val) def __exit__(self, exc_type, exc_value, traceback): _lib.PdfToolsPdf_Document_Close.argtypes = [c_void_p] _lib.PdfToolsPdf_Document_Close.restype = c_bool if self._handle is not None: try: if not _lib.PdfToolsPdf_Document_Close(self._handle): super()._throw_last_error() finally: self._handle = None # Invalidate the handle def __enter__(self): return self @staticmethod def _create_dynamic_type(handle): _lib.PdfToolsPdf_Document_GetType.argtypes = [c_void_p] _lib.PdfToolsPdf_Document_GetType.restype = c_int obj_type = _lib.PdfToolsPdf_Document_GetType(handle) # Create and return the object based on the type if obj_type == 0: return Document._from_handle(handle) elif obj_type == 1: from pdftools_sdk.sign.prepared_document import PreparedDocument return PreparedDocument._from_handle(handle) else: return None @classmethod def _from_handle(cls, handle): """ Internal factory method for constructing an instance using an internal handle. This method creates an instance of the class by bypassing the public constructor. """ instance = Document.__new__(cls) # Bypass __init__ instance._initialize(handle) return instance def _initialize(self, handle): super()._initialize(handle)