32
32
import weakref
33
33
from io import BytesIO , FileIO , UnsupportedOperation
34
34
from pathlib import Path
35
+ from types import TracebackType
35
36
from typing import (
36
37
Any ,
37
38
Callable ,
40
41
List ,
41
42
Optional ,
42
43
Tuple ,
44
+ Type ,
43
45
Union ,
44
46
cast ,
45
47
)
@@ -100,6 +102,9 @@ class PdfReader(PdfDocCommon):
100
102
password: Decrypt PDF file at initialization. If the
101
103
password is None, the file will not be decrypted.
102
104
Defaults to ``None``.
105
+
106
+ Can also be instantiated as a contextmanager which will automatically close
107
+ the underlying file pointer if passed via filenames.
103
108
"""
104
109
105
110
def __init__ (
@@ -123,8 +128,10 @@ def __init__(
123
128
__name__ ,
124
129
)
125
130
131
+ self ._opened_automatically = False
126
132
if isinstance (stream , (str , Path )):
127
133
stream = FileIO (stream , "rb" )
134
+ self ._opened_automatically = True
128
135
weakref .finalize (self , stream .close )
129
136
130
137
self .read (stream )
@@ -160,6 +167,20 @@ def close(self) -> None:
160
167
"""Close the underlying file handle"""
161
168
self .stream .close ()
162
169
170
+ def __enter__ (self ) -> "PdfReader" :
171
+ """Use PdfReader as context manager"""
172
+ return self
173
+
174
+ def __exit__ (
175
+ self ,
176
+ exc_type : Optional [Type [BaseException ]],
177
+ exc : Optional [BaseException ],
178
+ traceback : Optional [TracebackType ],
179
+ ) -> None :
180
+ """Close the underlying stream if owned by the PdfReader"""
181
+ if self ._opened_automatically :
182
+ self .close ()
183
+
163
184
@property
164
185
def root_object (self ) -> DictionaryObject :
165
186
"""Provide access to "/Root". standardized with PdfWriter."""
0 commit comments