Skip to content

Commit 6c55ab2

Browse files
authored
Merge pull request #7913 from nulano/types-cms2
2 parents a6c7a04 + 46b0b0e commit 6c55ab2

File tree

7 files changed

+291
-106
lines changed

7 files changed

+291
-106
lines changed

Tests/test_imagecms.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,22 @@
44
import os
55
import re
66
import shutil
7+
import sys
78
from io import BytesIO
89
from pathlib import Path
910
from typing import Any
1011

1112
import pytest
1213

13-
from PIL import Image, ImageMode, features
14+
from PIL import Image, ImageMode, ImageWin, features
1415

1516
from .helper import (
1617
assert_image,
1718
assert_image_equal,
1819
assert_image_similar,
1920
assert_image_similar_tofile,
2021
hopper,
22+
is_pypy,
2123
)
2224

2325
try:
@@ -213,6 +215,10 @@ def test_display_profile() -> None:
213215
# try fetching the profile for the current display device
214216
ImageCms.get_display_profile()
215217

218+
if sys.platform == "win32":
219+
ImageCms.get_display_profile(ImageWin.HDC(0))
220+
ImageCms.get_display_profile(ImageWin.HWND(0))
221+
216222

217223
def test_lab_color_profile() -> None:
218224
ImageCms.createProfile("LAB", 5000)
@@ -496,16 +502,34 @@ def test_non_ascii_path(tmp_path: Path) -> None:
496502

497503

498504
def test_profile_typesafety() -> None:
499-
"""Profile init type safety
500-
501-
prepatch, these would segfault, postpatch they should emit a typeerror
502-
"""
503-
505+
# does not segfault
504506
with pytest.raises(TypeError, match="Invalid type for Profile"):
505507
ImageCms.ImageCmsProfile(0).tobytes()
506508
with pytest.raises(TypeError, match="Invalid type for Profile"):
507509
ImageCms.ImageCmsProfile(1).tobytes()
508510

511+
# also check core function
512+
with pytest.raises(TypeError):
513+
ImageCms.core.profile_tobytes(0)
514+
with pytest.raises(TypeError):
515+
ImageCms.core.profile_tobytes(1)
516+
517+
if not is_pypy():
518+
# core profile should not be directly instantiable
519+
with pytest.raises(TypeError):
520+
ImageCms.core.CmsProfile()
521+
with pytest.raises(TypeError):
522+
ImageCms.core.CmsProfile(0)
523+
524+
525+
@pytest.mark.skipif(is_pypy(), reason="fails on PyPy")
526+
def test_transform_typesafety() -> None:
527+
# core transform should not be directly instantiable
528+
with pytest.raises(TypeError):
529+
ImageCms.core.CmsProfile()
530+
with pytest.raises(TypeError):
531+
ImageCms.core.CmsProfile(0)
532+
509533

510534
def assert_aux_channel_preserved(
511535
mode: str, transform_in_place: bool, preserved_channel: str

docs/conf.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,12 @@
121121
# generating warnings in “nitpicky mode”. Note that type should include the domain name
122122
# if present. Example entries would be ('py:func', 'int') or
123123
# ('envvar', 'LD_LIBRARY_PATH').
124-
# nitpick_ignore = []
124+
nitpick_ignore = [
125+
# Sphinx does not understand typing.Literal[-1]
126+
# Will be fixed in a future version.
127+
# https://github.com/sphinx-doc/sphinx/pull/11904
128+
("py:obj", "typing.Literal[-1, 1]"),
129+
]
125130

126131

127132
# -- Options for HTML output ----------------------------------------------

docs/reference/ImageCms.rst

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ can be easily displayed in a chromaticity diagram, for example).
7373
:canonical: PIL._imagingcms.CmsProfile
7474

7575
.. py:attribute:: creation_date
76-
:type: Optional[datetime.datetime]
76+
:type: datetime.datetime | None
7777

7878
Date and time this profile was first created (see 7.2.1 of ICC.1:2010).
7979

@@ -156,74 +156,74 @@ can be easily displayed in a chromaticity diagram, for example).
156156
not been calculated (see 7.2.18 of ICC.1:2010).
157157

158158
.. py:attribute:: copyright
159-
:type: Optional[str]
159+
:type: str | None
160160

161161
The text copyright information for the profile (see 9.2.21 of ICC.1:2010).
162162

163163
.. py:attribute:: manufacturer
164-
:type: Optional[str]
164+
:type: str | None
165165

166166
The (English) display string for the device manufacturer (see
167167
9.2.22 of ICC.1:2010).
168168

169169
.. py:attribute:: model
170-
:type: Optional[str]
170+
:type: str | None
171171

172172
The (English) display string for the device model of the device
173173
for which this profile is created (see 9.2.23 of ICC.1:2010).
174174

175175
.. py:attribute:: profile_description
176-
:type: Optional[str]
176+
:type: str | None
177177

178178
The (English) display string for the profile description (see
179179
9.2.41 of ICC.1:2010).
180180

181181
.. py:attribute:: target
182-
:type: Optional[str]
182+
:type: str | None
183183

184184
The name of the registered characterization data set, or the
185185
measurement data for a characterization target (see 9.2.14 of
186186
ICC.1:2010).
187187

188188
.. py:attribute:: red_colorant
189-
:type: Optional[tuple[tuple[float]]]
189+
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
190190

191191
The first column in the matrix used in matrix/TRC transforms (see 9.2.44 of ICC.1:2010).
192192

193193
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
194194

195195
.. py:attribute:: green_colorant
196-
:type: Optional[tuple[tuple[float]]]
196+
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
197197

198198
The second column in the matrix used in matrix/TRC transforms (see 9.2.30 of ICC.1:2010).
199199

200200
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
201201

202202
.. py:attribute:: blue_colorant
203-
:type: Optional[tuple[tuple[float]]]
203+
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
204204

205205
The third column in the matrix used in matrix/TRC transforms (see 9.2.4 of ICC.1:2010).
206206

207207
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
208208

209209
.. py:attribute:: luminance
210-
:type: Optional[tuple[tuple[float]]]
210+
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
211211

212212
The absolute luminance of emissive devices in candelas per square
213213
metre as described by the Y channel (see 9.2.32 of ICC.1:2010).
214214

215215
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
216216

217217
.. py:attribute:: chromaticity
218-
:type: Optional[tuple[tuple[float]]]
218+
:type: tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]] | None
219219

220220
The data of the phosphor/colorant chromaticity set used (red,
221221
green and blue channels, see 9.2.16 of ICC.1:2010).
222222

223223
The value is in the format ``((x, y, Y), (x, y, Y), (x, y, Y))``, if available.
224224

225225
.. py:attribute:: chromatic_adaption
226-
:type: tuple[tuple[float]]
226+
:type: tuple[tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]], tuple[tuple[float, float, float], tuple[float, float, float], tuple[float, float, float]]] | None
227227

228228
The chromatic adaption matrix converts a color measured using the
229229
actual illumination conditions and relative to the actual adopted
@@ -249,34 +249,34 @@ can be easily displayed in a chromaticity diagram, for example).
249249
9.2.19 of ICC.1:2010).
250250

251251
.. py:attribute:: colorimetric_intent
252-
:type: Optional[str]
252+
:type: str | None
253253

254254
4-character string (padded with whitespace) identifying the image
255255
state of PCS colorimetry produced using the colorimetric intent
256256
transforms (see 9.2.20 of ICC.1:2010 for details).
257257

258258
.. py:attribute:: perceptual_rendering_intent_gamut
259-
:type: Optional[str]
259+
:type: str | None
260260

261261
4-character string (padded with whitespace) identifying the (one)
262262
standard reference medium gamut (see 9.2.37 of ICC.1:2010 for
263263
details).
264264

265265
.. py:attribute:: saturation_rendering_intent_gamut
266-
:type: Optional[str]
266+
:type: str | None
267267

268268
4-character string (padded with whitespace) identifying the (one)
269269
standard reference medium gamut (see 9.2.37 of ICC.1:2010 for
270270
details).
271271

272272
.. py:attribute:: technology
273-
:type: Optional[str]
273+
:type: str | None
274274

275275
4-character string (padded with whitespace) identifying the device
276276
technology (see 9.2.47 of ICC.1:2010 for details).
277277

278278
.. py:attribute:: media_black_point
279-
:type: Optional[tuple[tuple[float]]]
279+
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
280280

281281
This tag specifies the media black point and is used for
282282
generating absolute colorimetry.
@@ -287,41 +287,41 @@ can be easily displayed in a chromaticity diagram, for example).
287287
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
288288

289289
.. py:attribute:: media_white_point_temperature
290-
:type: Optional[float]
290+
:type: float | None
291291

292292
Calculates the white point temperature (see the LCMS documentation
293293
for more information).
294294

295295
.. py:attribute:: viewing_condition
296-
:type: Optional[str]
296+
:type: str | None
297297

298298
The (English) display string for the viewing conditions (see
299299
9.2.48 of ICC.1:2010).
300300

301301
.. py:attribute:: screening_description
302-
:type: Optional[str]
302+
:type: str | None
303303

304304
The (English) display string for the screening conditions.
305305

306306
This tag was available in ICC 3.2, but it is removed from
307307
version 4.
308308

309309
.. py:attribute:: red_primary
310-
:type: Optional[tuple[tuple[float]]]
310+
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
311311

312312
The XYZ-transformed of the RGB primary color red (1, 0, 0).
313313

314314
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
315315

316316
.. py:attribute:: green_primary
317-
:type: Optional[tuple[tuple[float]]]
317+
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
318318

319319
The XYZ-transformed of the RGB primary color green (0, 1, 0).
320320

321321
The value is in the format ``((X, Y, Z), (x, y, Y))``, if available.
322322

323323
.. py:attribute:: blue_primary
324-
:type: Optional[tuple[tuple[float]]]
324+
:type: tuple[tuple[float, float, float], tuple[float, float, float]] | None
325325

326326
The XYZ-transformed of the RGB primary color blue (0, 0, 1).
327327

@@ -334,7 +334,7 @@ can be easily displayed in a chromaticity diagram, for example).
334334
documentation on LCMS).
335335

336336
.. py:attribute:: clut
337-
:type: dict[tuple[bool]]
337+
:type: dict[int, tuple[bool, bool, bool]] | None
338338

339339
Returns a dictionary of all supported intents and directions for
340340
the CLUT model.
@@ -353,7 +353,7 @@ can be easily displayed in a chromaticity diagram, for example).
353353
that intent is supported for that direction.
354354

355355
.. py:attribute:: intent_supported
356-
:type: dict[tuple[bool]]
356+
:type: dict[int, tuple[bool, bool, bool]] | None
357357

358358
Returns a dictionary of all supported intents and directions.
359359

@@ -372,7 +372,7 @@ can be easily displayed in a chromaticity diagram, for example).
372372

373373
There is one function defined on the class:
374374

375-
.. py:method:: is_intent_supported(intent, direction)
375+
.. py:method:: is_intent_supported(intent: int, direction: int, /)
376376
377377
Returns if the intent is supported for the given direction.
378378

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ ignore = [
117117
"E221", # Multiple spaces before operator
118118
"E226", # Missing whitespace around arithmetic operator
119119
"E241", # Multiple spaces after ','
120+
"PYI026", # flake8-pyi: typing.TypeAlias added in Python 3.10
120121
"PYI034", # flake8-pyi: typing.Self added in Python 3.11
121122
]
122123

0 commit comments

Comments
 (0)