Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pikepdf/__init__.py: 75%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# SPDX-FileCopyrightText: 2022 James R. Barlow
2# SPDX-License-Identifier: MPL-2.0
4"""A library for manipulating PDFs."""
6# isort:skip_file
8from __future__ import annotations
10from pikepdf._version import __version__
12try:
13 from pikepdf import _core
14except ImportError as _e: # pragma: no cover
15 _msg = "pikepdf's extension library failed to import"
16 raise ImportError(_msg) from _e
18from pikepdf._core import (
19 AccessMode,
20 AcroForm,
21 AcroFormField,
22 Annotation,
23 AnnotationFlag,
24 AttachedFileSpec,
25 ContentStreamInlineImage,
26 ContentStreamInstruction,
27 DataDecodingError,
28 DeletedObjectError,
29 ForeignObjectError,
30 FormFieldFlag,
31 Job,
32 JobUsageError,
33 Matrix,
34 NameTree,
35 NumberTree,
36 ObjectHelper,
37 ObjectStreamMode,
38 Page,
39 PasswordError,
40 Pdf,
41 PdfError,
42 Rectangle,
43 StreamDecodeLevel,
44 Token,
45 TokenFilter,
46 TokenType,
47)
48from pikepdf.exceptions import (
49 DependencyError,
50 OutlineStructureError,
51 UnsupportedImageTypeError,
52)
53from pikepdf.objects import (
54 Array,
55 Boolean,
56 Dictionary,
57 Integer,
58 Name,
59 NamePath,
60 Object,
61 ObjectType,
62 Operator,
63 Real,
64 Stream,
65 String,
66)
67from pikepdf.models import (
68 Encryption,
69 Outline,
70 OutlineItem,
71 PageLocation,
72 PdfImage,
73 PdfInlineImage,
74 Permissions,
75 make_page_destination,
76 parse_content_stream,
77 unparse_content_stream,
78)
80from pikepdf.models.ctm import (
81 get_objects_with_ctm,
82)
85# Importing these will monkeypatch classes defined in C++ and register a new
86# pdfdoc codec
87# While _cpphelpers is intended to be called from our C++ code only, explicitly
88# importing helps introspection tools like PyInstaller figure out that the module
89# is necessary.
90from pikepdf import _cpphelpers, _methods, codec # noqa: F401, F841
91from pikepdf import settings
92from pikepdf import exceptions
94__libqpdf_version__: str = _core.qpdf_version()
96# Conversion mode API
97from contextlib import contextmanager
98from typing import Literal
101def set_object_conversion_mode(mode: Literal['implicit', 'explicit']) -> None:
102 """Set global object conversion mode.
104 This controls how PDF scalar values (integers, booleans, reals) are
105 returned when accessing PDF objects.
107 Args:
108 mode: Conversion mode.
109 - ``'implicit'`` (default): Automatically convert PDF integers to
110 Python ``int``, booleans to ``bool``, and reals to ``Decimal``.
111 This is the legacy behavior.
112 - ``'explicit'``: Return PDF scalars as ``pikepdf.Integer``,
113 ``pikepdf.Boolean``, and ``pikepdf.Real`` objects. This enables
114 better type safety and static type checking.
116 Example:
117 >>> pikepdf.set_object_conversion_mode('explicit')
118 >>> pdf = pikepdf.open('test.pdf')
119 >>> count = pdf.Root.Count
120 >>> isinstance(count, pikepdf.Integer) # True in explicit mode
121 True
122 >>> int(count) # Convert to Python int
123 5
125 .. versionadded:: 10.1
126 """
127 _core._set_explicit_conversion_mode(mode == 'explicit')
130def get_object_conversion_mode() -> Literal['implicit', 'explicit']:
131 """Get current object conversion mode.
133 Returns:
134 The current conversion mode: ``'implicit'`` or ``'explicit'``.
136 .. versionadded:: 10.1
137 """
138 return 'explicit' if _core._get_explicit_conversion_mode() else 'implicit'
141@contextmanager
142def explicit_conversion():
143 """Context manager for explicit conversion mode.
145 Within this context, PDF scalar values will be returned as
146 ``pikepdf.Integer``, ``pikepdf.Boolean``, and ``pikepdf.Real`` objects
147 instead of being automatically converted to Python native types.
149 Example:
150 >>> with pikepdf.explicit_conversion():
151 ... pdf = pikepdf.open('test.pdf')
152 ... count = pdf.Root.Count
153 ... isinstance(count, pikepdf.Integer)
154 True
156 .. versionadded:: 10.1
157 """
158 old = _core._get_explicit_conversion_mode()
159 _core._set_explicit_conversion_mode(True)
160 try:
161 yield
162 finally:
163 _core._set_explicit_conversion_mode(old)
166# Provide pikepdf.{open, new} -> pikepdf.Pdf.{open, new}
167open = Pdf.open # pylint: disable=redefined-builtin
168new = Pdf.new
170# Exclude .open, .new here from to make sure from pikepdf import * does not clobber
171# builtins.open()
172# Exclude codec, objects, jbig2 because we import the interesting bits from them
173# directly to here.
174_exclude_from__all__ = {'open', 'new', 'codec', 'objects', 'jbig2'}
176__all__ = [
177 '__libqpdf_version__',
178 '__version__',
179 'AccessMode',
180 'AcroForm',
181 'AcroFormField',
182 'Annotation',
183 'AnnotationFlag',
184 'Array',
185 'AttachedFileSpec',
186 'Boolean',
187 'ContentStreamInlineImage',
188 'ContentStreamInstruction',
189 'DataDecodingError',
190 'DeletedObjectError',
191 'DependencyError',
192 'Dictionary',
193 'Encryption',
194 'exceptions',
195 'explicit_conversion',
196 'ForeignObjectError',
197 'FormFieldFlag',
198 'get_object_conversion_mode',
199 'get_objects_with_ctm',
200 'HifiPrintImageNotTranscodableError',
201 'Integer',
202 'InvalidPdfImageError',
203 'Job',
204 'JobUsageError',
205 'make_page_destination',
206 'Matrix',
207 'models',
208 'Name',
209 'NamePath',
210 'NameTree',
211 'NumberTree',
212 'Object',
213 'ObjectHelper',
214 'ObjectStreamMode',
215 'ObjectType',
216 'Operator',
217 'Outline',
218 'OutlineItem',
219 'OutlineStructureError',
220 'Page',
221 'PageLocation',
222 'parse_content_stream',
223 'PasswordError',
224 'Pdf',
225 'PdfError',
226 'PdfImage',
227 'PdfInlineImage',
228 'Permissions',
229 'Real',
230 'Rectangle',
231 'set_object_conversion_mode',
232 'settings',
233 'Stream',
234 'StreamDecodeLevel',
235 'String',
236 'Token',
237 'TokenFilter',
238 'TokenType',
239 'unparse_content_stream',
240 'UnsupportedImageTypeError',
241]