8000 MNT Removes externals._pilutil and uses Pillow directly (#22743) · scikit-learn/scikit-learn@a5c90f8 · GitHub
[go: up one dir, main page]

Skip to content

Commit a5c90f8

Browse files
authored
MNT Removes externals._pilutil and uses Pillow directly (#22743)
1 parent aee564c commit a5c90f8

File tree

6 files changed

+41
-529
lines changed

6 files changed

+41
-529
lines changed

sklearn/conftest.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
from sklearn.utils import _IS_32BIT
1212
from sklearn.utils._openmp_helpers import _openmp_effective_n_threads
13-
from sklearn.externals import _pilutil
1413
from sklearn._min_dependencies import PYTEST_MIN_VERSION
1514
from sklearn.utils.fixes import parse_version
1615
from sklearn.datasets import fetch_20newsgroups
@@ -185,7 +184,14 @@ def pytest_collection_modifyitems(config, items):
185184
# details.
186185
if item.name != "sklearn._config.config_context":
187186
item.add_marker(skip_marker)
188-
elif not _pilutil.pillow_installed:
187+
try:
188+
import PIL # noqa
189+
190+
pillow_installed = True
191+
except ImportError:
192+
pillow_installed = False
193+
194+
if not pillow_installed:
189195
skip_marker = pytest.mark.skip(reason="pillow (or PIL) not installed!")
190196
for item in items:
191197
if item.name in [

sklearn/datasets/_base.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,8 +1387,15 @@ def load_sample_images():
13871387
>>> first_img_data.dtype #doctest: +SKIP
13881388
dtype('uint8')
13891389
"""
1390-
# import PIL only when needed
1391-
from ..externals._pilutil import imread
1390+
try:
1391+
from PIL import Image
1392+
except ImportError:
1393+
raise ImportError(
1394+
"The Python Imaging Library (PIL) is required to load data "
1395+
"from jpeg files. Please refer to "
1396+
"https://pillow.readthedocs.io/en/stable/installation.html "
1397+
"for installing PIL."
1398+
)
13921399

13931400
descr = load_descr("README.txt", descr_module=IMAGES_MODULE)
13941401

@@ -1397,7 +1404,8 @@ def load_sample_images():
13971404
if filename.endswith(".jpg"):
13981405
filenames.append(filename)
13991406
with resources.open_binary(IMAGES_MODULE, filename) as image_file:
1400-
image = imread(image_file)
1407+
pil_image = Image.open(image_file)
1408+
image = np.asarray(pil_image)
14011409
images.append(image)
14021410

14031411
return Bunch(images=images, filenames=filenames, DESCR=descr)

sklearn/datasets/_lfw.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,15 @@ def _check_fetch_lfw(data_home=None, funneled=True, download_if_missing=True):
116116

117117
def _load_imgs(file_paths, slice_, color, resize):
118118
"""Internally used to load images"""
119-
# import PIL only when needed
120-
from ..externals._pilutil import imread, imresize
119+
try:
120+
from PIL import Image
121+
except ImportError:
122+
raise ImportError(
123+
"The Python Imaging Library (PIL) is required to load data "
124+
"from jpeg files. Please refer to "
125+
"https://pillow.readthedocs.io/en/stable/installation.html "
126+
"for installing PIL."
127+
)
121128

122129
# compute the portion of the images to load to respect the slice_ parameter
123130
# given by the caller
@@ -151,17 +158,19 @@ def _load_imgs(file_paths, slice_, color, resize):
151158

152159
# Checks if jpeg reading worked. Refer to issue #3594 for more
153160
# details.
154-
img = imread(file_path)
155-
if img.ndim == 0:
161+
pil_img = Image.open(file_path)
162+
pil_img.crop((w_slice.start, h_slice.start, w_slice.stop, h_slice.stop))
163+
if resize is not None:
164+
pil_img = pil_img.resize((w, h))
165+
face = np.asarray(pil_img, dtype=np.float32)
166+
167+
if face.ndim == 0:
156168
raise RuntimeError(
157169
"Failed to read the image file %s, "
158170
"Please make sure that libjpeg is installed" % file_path
159171
)
160172

161-
face = np.asarray(img[slice_], dtype=np.float32)
162173
face /= 255.0 # scale uint8 coded colors to the [0.0, 1.0] floats
163-
if resize is not None:
164-
face = imresize(face, resize)
165174
if not color:
166175
# average the color channels to compute a gray levels
167176
# representation

sklearn/datasets/tests/test_base.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
from sklearn.utils._testing import SkipTest
3131
from sklearn.datasets.tests.test_common import check_as_frame
3232

33-
from sklearn.externals._pilutil import pillow_installed
34-
3533

3634
def _remove_dir(path):
3735
if os.path.isdir(path):
@@ -226,11 +224,9 @@ def test_load_sample_image():
226224

227225

228226
def test_load_missing_sample_image_error():
229-
if pillow_installed:
230-
with pytest.raises(AttributeError):
231-
load_sample_image("blop.jpg")
232-
else:
233-
warnings.warn("Could not load sample images, PIL is not available.")
227+
pytest.importorskip("PIL")
228+
with pytest.raises(AttributeError):
229+
load_sample_image("blop.jpg")
234230

235231

236232
def test_load_diabetes_raw():

sklearn/datasets/tests/test_lfw.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@
1515
import numpy as np
1616
import pytest
1717
from functools import partial
18-
from sklearn.externals._pilutil import pillow_installed, imsave
1918
from sklearn.datasets import fetch_lfw_pairs
2019
from sklearn.datasets import fetch_lfw_people
2120

2221
from sklearn.utils._testing import assert_array_equal
23-
from sklearn.utils._testing import SkipTest
2422
from sklearn.datasets.tests.test_common import check_return_X_y
2523

2624

@@ -41,8 +39,7 @@
4139

4240
def setup_module():
4341
"""Test fixture run once and common to all tests of this module"""
44-
if not pillow_installed:
45-
raise SkipTest("PIL not installed.")
42+
Image = pytest.importorskip("PIL.Image")
4643

4744
global SCIKIT_LEARN_DATA, SCIKIT_LEARN_EMPTY_DATA, LFW_HOME
4845

@@ -69,10 +66,8 @@ def setup_module():
6966
for i in range(n_faces):
7067
file_path = os.path.join(folder_name, name + "_%04d.jpg" % i)
7168
uniface = np_rng.randint(0, 255, size=(250, 250, 3))
72-
try:
73-
imsave(file_path, uniface)
74-
except ImportError:
75-
raise SkipTest("PIL not installed")
69+
img = Image.fromarray(uniface.astype(np.uint8))
70+
img.save(file_path)
7671

7772
# add some random file pollution to test robustness
7873
with open(os.path.join(LFW_HOME, "lfw_funneled", ".test.swp"), "wb") as f:

0 commit comments

Comments
 (0)
0