Skip to content

Commit 0ca4d37

Browse files
authored
BUG: Cope with indirect objects in filters and remove deprecated code (#2177)
closes #2158 closes #2159
1 parent f68138c commit 0ca4d37

File tree

2 files changed

+46
-54
lines changed

2 files changed

+46
-54
lines changed

pypdf/filters.py

Lines changed: 42 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from ._utils import (
4444
b_,
4545
deprecate_with_replacement,
46+
deprecation_no_replacement,
4647
logger_warning,
4748
ord_,
4849
)
@@ -53,7 +54,7 @@
5354
from .constants import ImageAttributes as IA
5455
from .constants import LzwFilterParameters as LZW
5556
from .constants import StreamAttributes as SA
56-
from .errors import PdfReadError, PdfStreamError
57+
from .errors import DeprecationError, PdfReadError, PdfStreamError
5758
from .generic import (
5859
ArrayObject,
5960
DictionaryObject,
@@ -93,7 +94,7 @@ class FlateDecode:
9394
@staticmethod
9495
def decode(
9596
data: bytes,
96-
decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
97+
decode_parms: Optional[DictionaryObject] = None,
9798
**kwargs: Any,
9899
) -> bytes:
99100
"""
@@ -113,42 +114,37 @@ def decode(
113114
if "decodeParms" in kwargs: # deprecated
114115
deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
115116
decode_parms = kwargs["decodeParms"]
117+
if isinstance(decode_parms, ArrayObject): # type: ignore
118+
raise DeprecationError("decode_parms as ArrayObject is depreciated")
119+
116120
str_data = decompress(data)
117121
predictor = 1
118122

119123
if decode_parms:
120124
try:
121-
if isinstance(decode_parms, ArrayObject):
122-
for decode_parm in decode_parms:
123-
if "/Predictor" in decode_parm:
124-
predictor = decode_parm["/Predictor"]
125-
else:
126-
predictor = decode_parms.get("/Predictor", 1)
125+
predictor = decode_parms.get("/Predictor", 1)
127126
except (AttributeError, TypeError): # Type Error is NullObject
128127
pass # Usually an array with a null object was read
129128
# predictor 1 == no predictor
130129
if predictor != 1:
131130
# The /Columns param. has 1 as the default value; see ISO 32000,
132131
# §7.4.4.3 LZWDecode and FlateDecode Parameters, Table 8
133132
DEFAULT_BITS_PER_COMPONENT = 8
134-
if isinstance(decode_parms, ArrayObject):
133+
try:
134+
columns = cast(int, decode_parms[LZW.COLUMNS].get_object()) # type: ignore
135+
except (TypeError, KeyError):
135136
columns = 1
136-
bits_per_component = DEFAULT_BITS_PER_COMPONENT
137-
for decode_parm in decode_parms:
138-
if "/Columns" in decode_parm:
139-
columns = decode_parm["/Columns"]
140-
if LZW.BITS_PER_COMPONENT in decode_parm:
141-
bits_per_component = decode_parm[LZW.BITS_PER_COMPONENT]
142-
else:
143-
columns = (
144-
1 if decode_parms is None else decode_parms.get(LZW.COLUMNS, 1)
145-
)
146-
colors = 1 if decode_parms is None else decode_parms.get(LZW.COLORS, 1)
147-
bits_per_component = (
148-
decode_parms.get(LZW.BITS_PER_COMPONENT, DEFAULT_BITS_PER_COMPONENT)
149-
if decode_parms
150-
else DEFAULT_BITS_PER_COMPONENT
137+
try:
138+
colors = cast(int, decode_parms[LZW.COLORS].get_object()) # type: ignore
139+
except (TypeError, KeyError):
140+
colors = 1
141+
try:
142+
bits_per_component = cast(
143+
int,
144+
decode_parms[LZW.BITS_PER_COMPONENT].get_object(), # type: ignore
151145
)
146+
except (TypeError, KeyError):
147+
bits_per_component = DEFAULT_BITS_PER_COMPONENT
152148

153149
# PNG predictor can vary by row and so is the lead byte on each row
154150
rowlength = (
@@ -259,7 +255,7 @@ class ASCIIHexDecode:
259255
@staticmethod
260256
def decode(
261257
data: Union[str, bytes],
262-
decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
258+
decode_parms: Optional[DictionaryObject] = None,
263259
**kwargs: Any,
264260
) -> bytes:
265261
"""
@@ -278,9 +274,8 @@ def decode(
278274
Raises:
279275
PdfStreamError:
280276
"""
281-
if "decodeParms" in kwargs: # deprecated
282-
deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
283-
decode_parms = kwargs["decodeParms"] # noqa: F841
277+
# decode_parms is unused here
278+
284279
if isinstance(data, str):
285280
data = data.encode()
286281
retval = b""
@@ -321,7 +316,7 @@ class RunLengthDecode:
321316
@staticmethod
322317
def decode(
323318
data: bytes,
324-
decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
319+
decode_parms: Optional[DictionaryObject] = None,
325320
**kwargs: Any,
326321
) -> bytes:
327322
"""
@@ -337,9 +332,8 @@ def decode(
337332
Raises:
338333
PdfStreamError:
339334
"""
340-
if "decodeParms" in kwargs: # deprecated
341-
deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
342-
decode_parms = kwargs["decodeParms"] # noqa: F841
335+
# decode_parms is unused here
336+
343337
lst = []
344338
index = 0
345339
while True:
@@ -453,7 +447,7 @@ def decode(self) -> str:
453447
@staticmethod
454448
def decode(
455449
data: bytes,
456-
decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
450+
decode_parms: Optional[DictionaryObject] = None,
457451
**kwargs: Any,
458452
) -> str:
459453
"""
@@ -466,9 +460,8 @@ def decode(
466460
Returns:
467461
decoded data.
468462
"""
469-
if "decodeParms" in kwargs: # deprecated
470-
deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
471-
decode_parms = kwargs["decodeParms"] # noqa: F841
463+
# decode_parms is unused here
464+
472465
return LZWDecode.Decoder(data).decode()
473466

474467

@@ -478,12 +471,11 @@ class ASCII85Decode:
478471
@staticmethod
479472
def decode(
480473
data: Union[str, bytes],
481-
decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
474+
decode_parms: Optional[DictionaryObject] = None,
482475
**kwargs: Any,
483476
) -> bytes:
484-
if "decodeParms" in kwargs: # deprecated
485-
deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
486-
decode_parms = kwargs["decodeParms"] # noqa: F841
477+
# decode_parms is unused here
478+
487479
if isinstance(data, str):
488480
data = data.encode("ascii")
489481
group_index = b = 0
@@ -511,25 +503,21 @@ class DCTDecode:
511503
@staticmethod
512504
def decode(
513505
data: bytes,
514-
decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
506+
decode_parms: Optional[DictionaryObject] = None,
515507
**kwargs: Any,
516508
) -> bytes:
517-
if "decodeParms" in kwargs: # deprecated
518-
deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
519-
decode_parms = kwargs["decodeParms"] # noqa: F841
509+
# decode_parms is unused here
520510
return data
521511

522512

523513
class JPXDecode:
524514
@staticmethod
525515
def decode(
526516
data: bytes,
527-
decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
517+
decode_parms: Optional[DictionaryObject] = None,
528518
**kwargs: Any,
529519
) -> bytes:
530-
if "decodeParms" in kwargs: # deprecated
531-
deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
532-
decode_parms = kwargs["decodeParms"] # noqa: F841
520+
# decode_parms is unused here
533521
return data
534522

535523

@@ -591,13 +579,18 @@ def _get_parameters(
591579
@staticmethod
592580
def decode(
593581
data: bytes,
594-
decode_parms: Union[None, ArrayObject, DictionaryObject] = None,
582+
decode_parms: Optional[DictionaryObject] = None,
595583
height: int = 0,
596584
**kwargs: Any,
597585
) -> bytes:
586+
# decode_parms is unused here
598587
if "decodeParms" in kwargs: # deprecated
599588
deprecate_with_replacement("decodeParms", "parameters", "4.0.0")
600589
decode_parms = kwargs["decodeParms"]
590+
if isinstance(decode_parms, ArrayObject): # deprecated
591+
deprecation_no_replacement(
592+
"decode_parms being an ArrayObject", removed_in="3.15.5"
593+
)
601594
parms = CCITTFaxDecode._get_parameters(decode_parms, height)
602595

603596
img_size = len(data)

tests/test_filters.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from PIL import Image
1111

1212
from pypdf import PdfReader
13-
from pypdf.errors import PdfReadError, PdfStreamError
13+
from pypdf.errors import DeprecationError, PdfReadError, PdfStreamError
1414
from pypdf.filters import (
1515
ASCII85Decode,
1616
ASCIIHexDecode,
@@ -69,16 +69,15 @@ def test_flatedecode_unsupported_predictor():
6969
codec.decode(codec.encode(s), DictionaryObject({"/Predictor": predictor}))
7070

7171

72-
@pytest.mark.parametrize(
73-
"params", [ArrayObject([]), ArrayObject([{"/Predictor": 1}]), "a"]
74-
)
72+
@pytest.mark.parametrize("params", [ArrayObject([]), ArrayObject([{"/Predictor": 1}])])
7573
def test_flate_decode_decompress_with_array_params(params):
7674
"""FlateDecode decode() method works correctly with array parameters."""
7775
codec = FlateDecode()
7876
s = ""
7977
s = s.encode()
8078
encoded = codec.encode(s)
81-
assert codec.decode(encoded, params) == s
79+
with pytest.raises(DeprecationError):
80+
assert codec.decode(encoded, params) == s
8281

8382

8483
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)