Skip to content

Commit 7972332

Browse files
committed
Added type hints
1 parent dd753f4 commit 7972332

3 files changed

Lines changed: 33 additions & 17 deletions

File tree

src/PIL/Image.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ def getmodebandnames(mode):
282282
return ImageMode.getmode(mode).bands
283283

284284

285-
def getmodebands(mode):
285+
def getmodebands(mode: str) -> int:
286286
"""
287287
Gets the number of individual bands for this mode.
288288

src/PIL/ImageFile.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,8 @@ def extents(self):
616616

617617

618618
class PyCodec:
619+
fd: io.BytesIO | None
620+
619621
def __init__(self, mode, *args):
620622
self.im = None
621623
self.state = PyCodecState()

src/PIL/PpmImagePlugin.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from __future__ import annotations
1717

1818
import math
19+
from io import BytesIO
1920

2021
from . import Image, ImageFile
2122
from ._binary import i16be as i16
@@ -45,7 +46,7 @@
4546
}
4647

4748

48-
def _accept(prefix):
49+
def _accept(prefix: bytes) -> bool:
4950
return prefix[0:1] == b"P" and prefix[1] in b"0123456fy"
5051

5152

@@ -57,7 +58,9 @@ class PpmImageFile(ImageFile.ImageFile):
5758
format = "PPM"
5859
format_description = "Pbmplus image"
5960

60-
def _read_magic(self):
61+
def _read_magic(self) -> bytes:
62+
assert self.fp is not None
63+
6164
magic = b""
6265
# read until whitespace or longest available magic number
6366
for _ in range(6):
@@ -67,7 +70,9 @@ def _read_magic(self):
6770
magic += c
6871
return magic
6972

70-
def _read_token(self):
73+
def _read_token(self) -> bytes:
74+
assert self.fp is not None
75+
7176
token = b""
7277
while len(token) <= 10: # read until next whitespace or limit of 10 characters
7378
c = self.fp.read(1)
@@ -93,7 +98,9 @@ def _read_token(self):
9398
raise ValueError(msg)
9499
return token
95100

96-
def _open(self):
101+
def _open(self) -> None:
102+
assert self.fp is not None
103+
97104
magic_number = self._read_magic()
98105
try:
99106
mode = MODES[magic_number]
@@ -114,6 +121,8 @@ def _open(self):
114121
decoder_name = "raw"
115122
if magic_number in (b"P1", b"P2", b"P3"):
116123
decoder_name = "ppm_plain"
124+
125+
args: str | tuple[str | int, ...]
117126
if mode == "1":
118127
args = "1;I"
119128
elif mode == "F":
@@ -151,16 +160,19 @@ def _open(self):
151160

152161
class PpmPlainDecoder(ImageFile.PyDecoder):
153162
_pulls_fd = True
163+
_comment_spans: bool
164+
165+
def _read_block(self) -> bytes:
166+
assert self.fd is not None
154167

155-
def _read_block(self):
156168
return self.fd.read(ImageFile.SAFEBLOCK)
157169

158-
def _find_comment_end(self, block, start=0):
170+
def _find_comment_end(self, block: bytes, start: int = 0) -> int:
159171
a = block.find(b"\n", start)
160172
b = block.find(b"\r", start)
161173
return min(a, b) if a * b > 0 else max(a, b) # lowest nonnegative index (or -1)
162174

163-
def _ignore_comments(self, block):
175+
def _ignore_comments(self, block: bytes) -> bytes:
164176
if self._comment_spans:
165177
# Finish current comment
166178
while block:
@@ -194,7 +206,7 @@ def _ignore_comments(self, block):
194206
break
195207
return block
196208

197-
def _decode_bitonal(self):
209+
def _decode_bitonal(self) -> bytearray:
198210
"""
199211
This is a separate method because in the plain PBM format, all data tokens are
200212
exactly one byte, so the inter-token whitespace is optional.
@@ -219,15 +231,15 @@ def _decode_bitonal(self):
219231
invert = bytes.maketrans(b"01", b"\xFF\x00")
220232
return data.translate(invert)
221233

222-
def _decode_blocks(self, maxval):
234+
def _decode_blocks(self, maxval: int) -> bytearray:
223235
data = bytearray()
224236
max_len = 10
225237
out_byte_count = 4 if self.mode == "I" else 1
226238
out_max = 65535 if self.mode == "I" else 255
227239
bands = Image.getmodebands(self.mode)
228240
total_bytes = self.state.xsize * self.state.ysize * bands * out_byte_count
229241

230-
half_token = False
242+
half_token = b""
231243
while len(data) != total_bytes:
232244
block = self._read_block() # read next block
233245
if not block:
@@ -241,7 +253,7 @@ def _decode_blocks(self, maxval):
241253

242254
if half_token:
243255
block = half_token + block # stitch half_token to new block
244-
half_token = False
256+
half_token = b""
245257

246258
tokens = block.split()
247259

@@ -259,15 +271,15 @@ def _decode_blocks(self, maxval):
259271
raise ValueError(msg)
260272
value = int(token)
261273
if value > maxval:
262-
msg = f"Channel value too large for this mode: {value}"
263-
raise ValueError(msg)
274+
msg_str = f"Channel value too large for this mode: {value}"
275+
raise ValueError(msg_str)
264276
value = round(value / maxval * out_max)
265277
data += o32(value) if self.mode == "I" else o8(value)
266278
if len(data) == total_bytes: # finished!
267279
break
268280
return data
269281

270-
def decode(self, buffer):
282+
def decode(self, buffer: bytes) -> tuple[int, int]:
271283
self._comment_spans = False
272284
if self.mode == "1":
273285
data = self._decode_bitonal()
@@ -283,7 +295,9 @@ def decode(self, buffer):
283295
class PpmDecoder(ImageFile.PyDecoder):
284296
_pulls_fd = True
285297

286-
def decode(self, buffer):
298+
def decode(self, buffer: bytes) -> tuple[int, int]:
299+
assert self.fd is not None
300+
287301
data = bytearray()
288302
maxval = self.args[-1]
289303
in_byte_count = 1 if maxval < 256 else 2
@@ -310,7 +324,7 @@ def decode(self, buffer):
310324
# --------------------------------------------------------------------
311325

312326

313-
def _save(im, fp, filename):
327+
def _save(im: Image.Image, fp: BytesIO, filename: str) -> None:
314328
if im.mode == "1":
315329
rawmode, head = "1;I", b"P4"
316330
elif im.mode == "L":

0 commit comments

Comments
 (0)