From 7afbb00ba5c06c4b942c50ca862d6cf756460e3c Mon Sep 17 00:00:00 2001 From: Benjamin Gilbert Date: Sun, 13 Sep 2020 15:15:31 -0400 Subject: [PATCH] Drop fallback code for missing extension module The fallback code originally ran if OpenSlide Python was installed --without-performance, but setuptools 46 dropped the Feature mechanism and 298b5a9a163e removed --without-performance from setup.py. There is now no mechanism for providing default-enabled optional features in Python packages. The fallback case was originally added for Windows users who don't have MSVC installed, but we now distribute precompiled Python wheels for Windows, so it should be okay to just require the compiled module. --- openslide/lowlevel.py | 59 +++++------------------------------------ tests/__init__.py | 7 ----- tests/test_openslide.py | 12 ++------- 3 files changed, 9 insertions(+), 69 deletions(-) diff --git a/openslide/lowlevel.py b/openslide/lowlevel.py index 22704c2d..7e771b5d 100644 --- a/openslide/lowlevel.py +++ b/openslide/lowlevel.py @@ -37,6 +37,8 @@ import platform import sys +from . import _convert + if platform.system() == 'Windows': _lib = cdll.LoadLibrary('libopenslide-0.dll') elif platform.system() == 'Darwin': @@ -57,58 +59,6 @@ else: _lib = cdll.LoadLibrary('libopenslide.so.0') -try: - from . import _convert - def _load_image(buf, size): - '''buf must be a mutable buffer.''' - _convert.argb2rgba(buf) - return PIL.Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1) -except ImportError: - def _load_image(buf, size): - '''buf must be a buffer.''' - - # Load entire buffer at once if possible - MAX_PIXELS_PER_LOAD = (1 << 29) - 1 - # Otherwise, use chunks smaller than the maximum to reduce memory - # requirements - PIXELS_PER_LOAD = 1 << 26 - - def do_load(buf, size): - '''buf can be a string, but should be a ctypes buffer to avoid an - extra copy in the caller.''' - # First reorder the bytes in a pixel from native-endian aRGB to - # big-endian RGBa to work around limitations in RGBa loader - rawmode = (sys.byteorder == 'little') and 'BGRA' or 'ARGB' - buf = PIL.Image.frombuffer('RGBA', size, buf, 'raw', rawmode, 0, 1) - # Image.tobytes() is named tostring() in Pillow 1.x and PIL - buf = (getattr(buf, 'tobytes', None) or buf.tostring)() - # Now load the image as RGBA, undoing premultiplication - return PIL.Image.frombuffer('RGBA', size, buf, 'raw', 'RGBa', 0, 1) - - # Fast path for small buffers - w, h = size - if w * h <= MAX_PIXELS_PER_LOAD: - return do_load(buf, size) - - # Load in chunks to avoid OverflowError in PIL.Image.frombuffer() - # https://github.com/python-pillow/Pillow/issues/1475 - if w > PIXELS_PER_LOAD: - # We could support this, but it seems like overkill - raise ValueError('Width %d is too large (maximum %d)' % - (w, PIXELS_PER_LOAD)) - rows_per_load = PIXELS_PER_LOAD // w - img = PIL.Image.new('RGBA', (w, h)) - for y in range(0, h, rows_per_load): - rows = min(h - y, rows_per_load) - if sys.version[0] == '2': - chunk = buffer(buf, 4 * y * w, 4 * rows * w) - else: - # PIL.Image.frombuffer() won't take a memoryview or - # bytearray, so we can't avoid copying - chunk = memoryview(buf)[y * w:(y + rows) * w].tobytes() - img.paste(do_load(chunk, (w, rows)), (0, y)) - return img - class OpenSlideError(Exception): """An error produced by the OpenSlide library. @@ -167,6 +117,11 @@ def from_param(cls, obj): else: raise TypeError('Incorrect type') +def _load_image(buf, size): + '''buf must be a mutable buffer.''' + _convert.argb2rgba(buf) + return PIL.Image.frombuffer('RGBA', size, buf, 'raw', 'RGBA', 0, 1) + # check for errors opening an image file and wrap the resulting handle def _check_open(result, _func, _args): if result is None: diff --git a/tests/__init__.py b/tests/__init__.py index d2158b3d..3be04922 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -22,13 +22,6 @@ from PIL import Image import unittest -try: - import openslide._convert as _ - have_optimizations = True -except ImportError: - have_optimizations = False - - # PIL.Image cannot have zero width or height on Pillow 3.4.0 - 3.4.2 # https://github.com/python-pillow/Pillow/issues/2259 try: diff --git a/tests/test_openslide.py b/tests/test_openslide.py index f3d12df4..9b781368 100644 --- a/tests/test_openslide.py +++ b/tests/test_openslide.py @@ -25,8 +25,7 @@ import sys import unittest -from . import (file_path, have_optimizations, image_dimensions_cannot_be_zero, - skip_if) +from . import file_path, image_dimensions_cannot_be_zero, skip_if # Tests should be written to be compatible with Python 2.6 unittest. @@ -127,8 +126,7 @@ def test_read_region_bad_size(self): @skip_if(sys.maxsize < 1 << 32, '32-bit Python') # Broken on PIL and on Pillow >= 3.4.0, < 6.2.0. # https://github.com/python-pillow/Pillow/issues/3963 - @skip_if(have_optimizations and - [int(i) for i in getattr(Image, '__version__', '0').split('.')] < [6,2,0], + @skip_if([int(i) for i in getattr(Image, '__version__', '0').split('.')] < [6,2,0], 'broken on PIL and Pillow < 6.2.0') # Disabled to avoid OOM killer on small systems, since the stdlib # doesn't provide a way to find out how much RAM we have @@ -137,12 +135,6 @@ def _test_read_region_2GB(self): self.osr.read_region((1000, 1000), 0, (32768, 16384)).size, (32768, 16384)) - @skip_if(have_optimizations, 'only relevant --without-performance') - @skip_if(sys.maxsize < 1 << 32, '32-bit Python') - def test_read_region_2GB_width(self): - self.assertRaises(ValueError, - lambda: self.osr.read_region((1000, 1000), 0, (1 << 29, 1))) - def test_thumbnail(self): self.assertEqual(self.osr.get_thumbnail((100, 100)).size, (100, 83))