Converted common Qt test classes

This commit is contained in:
Andrew Murray 2020-03-27 20:30:00 +11:00
parent 748739c992
commit a8637449b9
7 changed files with 120 additions and 107 deletions

View File

@ -3,7 +3,6 @@ import pytest
from PIL import FontFile, Image, ImageDraw, ImageFont, PcfFontFile from PIL import FontFile, Image, ImageDraw, ImageFont, PcfFontFile
from .helper import ( from .helper import (
PillowTestCase,
assert_image_equal, assert_image_equal,
assert_image_similar, assert_image_similar,
skip_unless_feature, skip_unless_feature,
@ -16,6 +15,7 @@ message = "hello, world"
pytestmark = skip_unless_feature("zlib") pytestmark = skip_unless_feature("zlib")
def save_font(request, tmp_path): def save_font(request, tmp_path):
with open(fontname, "rb") as test_file: with open(fontname, "rb") as test_file:
font = PcfFontFile.PcfFontFile(test_file) font = PcfFontFile.PcfFontFile(test_file)
@ -30,6 +30,7 @@ def save_font(request, tmp_path):
os.remove(tempname[:-4] + ".pbm") os.remove(tempname[:-4] + ".pbm")
except OSError: except OSError:
pass # report? pass # report?
request.addfinalizer(delete_tempfile) request.addfinalizer(delete_tempfile)
font.save(tempname) font.save(tempname)
@ -42,14 +43,17 @@ def save_font(request, tmp_path):
assert f_loaded.read() == f_target.read() assert f_loaded.read() == f_target.read()
return tempname return tempname
def test_sanity(request, tmp_path): def test_sanity(request, tmp_path):
save_font(request, tmp_path) save_font(request, tmp_path)
def test_invalid_file(): def test_invalid_file():
with open("Tests/images/flower.jpg", "rb") as fp: with open("Tests/images/flower.jpg", "rb") as fp:
with pytest.raises(SyntaxError): with pytest.raises(SyntaxError):
PcfFontFile.PcfFontFile(fp) PcfFontFile.PcfFontFile(fp)
def test_draw(request, tmp_path): def test_draw(request, tmp_path):
tempname = save_font(request, tmp_path) tempname = save_font(request, tmp_path)
font = ImageFont.load(tempname) font = ImageFont.load(tempname)
@ -59,6 +63,7 @@ def test_draw(request, tmp_path):
with Image.open("Tests/images/test_draw_pbm_target.png") as target: with Image.open("Tests/images/test_draw_pbm_target.png") as target:
assert_image_similar(im, target, 0) assert_image_similar(im, target, 0)
def test_textsize(request, tmp_path): def test_textsize(request, tmp_path):
tempname = save_font(request, tmp_path) tempname = save_font(request, tmp_path)
font = ImageFont.load(tempname) font = ImageFont.load(tempname)
@ -70,6 +75,7 @@ def test_textsize(request, tmp_path):
msg = message[: l + 1] msg = message[: l + 1]
assert font.getsize(msg) == (len(msg) * 10, 20) assert font.getsize(msg) == (len(msg) * 10, 20)
def _test_high_characters(request, tmp_path, message): def _test_high_characters(request, tmp_path, message):
tempname = save_font(request, tmp_path) tempname = save_font(request, tmp_path)
font = ImageFont.load(tempname) font = ImageFont.load(tempname)
@ -79,6 +85,7 @@ def _test_high_characters(request, tmp_path, message):
with Image.open("Tests/images/high_ascii_chars.png") as target: with Image.open("Tests/images/high_ascii_chars.png") as target:
assert_image_similar(im, target, 0) assert_image_similar(im, target, 0)
def test_high_characters(request, tmp_path): def test_high_characters(request, tmp_path):
message = "".join(chr(i + 1) for i in range(140, 232)) message = "".join(chr(i + 1) for i in range(140, 232))
_test_high_characters(request, tmp_path, message) _test_high_characters(request, tmp_path, message)

View File

@ -1,12 +1,13 @@
import pytest import pytest
from PIL import Image, ImageQt from PIL import Image, ImageQt
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
from .test_imageqt import skip_if_qt_is_not_installed from .test_imageqt import skip_if_qt_is_not_installed
pytestmark = skip_if_qt_is_not_installed() pytestmark = skip_if_qt_is_not_installed()
@pytest.fixture @pytest.fixture
def test_images(): def test_images():
ims = [ ims = [
@ -20,6 +21,7 @@ def test_images():
for im in ims.values(): for im in ims.values():
im.close() im.close()
def roundtrip(expected): def roundtrip(expected):
# PIL -> Qt # PIL -> Qt
intermediate = expected.toqimage() intermediate = expected.toqimage()
@ -31,22 +33,27 @@ def roundtrip(expected):
else: else:
assert_image_equal(result, expected.convert("RGB")) assert_image_equal(result, expected.convert("RGB"))
def test_sanity_1(test_images): def test_sanity_1(test_images):
for im in test_images: for im in test_images:
roundtrip(im.convert("1")) roundtrip(im.convert("1"))
def test_sanity_rgb(test_images): def test_sanity_rgb(test_images):
for im in test_images: for im in test_images:
roundtrip(im.convert("RGB")) roundtrip(im.convert("RGB"))
def test_sanity_rgba(test_images): def test_sanity_rgba(test_images):
for im in test_images: for im in test_images:
roundtrip(im.convert("RGBA")) roundtrip(im.convert("RGBA"))
def test_sanity_l(test_images): def test_sanity_l(test_images):
for im in test_images: for im in test_images:
roundtrip(im.convert("L")) roundtrip(im.convert("L"))
def test_sanity_p(test_images): def test_sanity_p(test_images):
for im in test_images: for im in test_images:
roundtrip(im.convert("P")) roundtrip(im.convert("P"))

View File

@ -1,8 +1,6 @@
import pytest import pytest
from PIL import Image, ImageFilter from PIL import Image, ImageFilter
from .helper import PillowTestCase
@pytest.fixture @pytest.fixture
def test_images(): def test_images():

View File

@ -1,7 +1,7 @@
import pytest import pytest
from PIL import ImageQt from PIL import ImageQt
from .helper import PillowTestCase, hopper from .helper import hopper
if ImageQt.qt_is_installed: if ImageQt.qt_is_installed:
from PIL.ImageQt import qRgba from PIL.ImageQt import qRgba
@ -9,6 +9,23 @@ if ImageQt.qt_is_installed:
def skip_if_qt_is_not_installed(): def skip_if_qt_is_not_installed():
pass pass
@pytest.fixture
def qpixmap_app():
try:
if ImageQt.qt_version == "5":
from PyQt5.QtGui import QGuiApplication
elif ImageQt.qt_version == "side2":
from PySide2.QtGui import QGuiApplication
except ImportError:
pytest.skip("QGuiApplication not installed")
return
app = QGuiApplication([])
try:
yield
finally:
app.quit()
else: else:
@ -16,57 +33,34 @@ else:
return pytest.mark.skip(reason="Qt bindings are not installed") return pytest.mark.skip(reason="Qt bindings are not installed")
class PillowQtTestCase: pytestmark = skip_if_qt_is_not_installed()
def setUp(self):
skip_if_qt_is_not_installed(self)
def tearDown(self):
pass
class PillowQPixmapTestCase(PillowQtTestCase): def test_rgb():
def setUp(self): # from https://doc.qt.io/archives/qt-4.8/qcolor.html
super().setUp() # typedef QRgb
try: # An ARGB quadruplet on the format #AARRGGBB,
if ImageQt.qt_version == "5": # equivalent to an unsigned int.
from PyQt5.QtGui import QGuiApplication if ImageQt.qt_version == "5":
elif ImageQt.qt_version == "side2": from PyQt5.QtGui import qRgb
from PySide2.QtGui import QGuiApplication elif ImageQt.qt_version == "side2":
except ImportError: from PySide2.QtGui import qRgb
self.skipTest("QGuiApplication not installed")
self.app = QGuiApplication([]) assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255)
def tearDown(self): def checkrgb(r, g, b):
super().tearDown() val = ImageQt.rgb(r, g, b)
self.app.quit() val = val % 2 ** 24 # drop the alpha
assert val >> 16 == r
assert ((val >> 8) % 2 ** 8) == g
assert val % 2 ** 8 == b
checkrgb(0, 0, 0)
checkrgb(255, 0, 0)
checkrgb(0, 255, 0)
checkrgb(0, 0, 255)
class TestImageQt(PillowQtTestCase, PillowTestCase): def test_image():
def test_rgb(self): for mode in ("1", "RGB", "RGBA", "L", "P"):
# from https://doc.qt.io/archives/qt-4.8/qcolor.html ImageQt.ImageQt(hopper(mode))
# typedef QRgb
# An ARGB quadruplet on the format #AARRGGBB,
# equivalent to an unsigned int.
if ImageQt.qt_version == "5":
from PyQt5.QtGui import qRgb
elif ImageQt.qt_version == "side2":
from PySide2.QtGui import qRgb
assert qRgb(0, 0, 0) == qRgba(0, 0, 0, 255)
def checkrgb(r, g, b):
val = ImageQt.rgb(r, g, b)
val = val % 2 ** 24 # drop the alpha
assert val >> 16 == r
assert ((val >> 8) % 2 ** 8) == g
assert val % 2 ** 8 == b
checkrgb(0, 0, 0)
checkrgb(255, 0, 0)
checkrgb(0, 255, 0)
checkrgb(0, 0, 255)
def test_image(self):
for mode in ("1", "RGB", "RGBA", "L", "P"):
ImageQt.ImageQt(hopper(mode))

View File

@ -1,15 +1,18 @@
import pytest
from PIL import ImageQt from PIL import ImageQt
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
from .test_imageqt import PillowQPixmapTestCase from .test_imageqt import qpixmap_app, skip_if_qt_is_not_installed
pytestmark = skip_if_qt_is_not_installed()
class TestFromQPixmap(PillowQPixmapTestCase, PillowTestCase): def roundtrip(expected):
def roundtrip(self, expected): result = ImageQt.fromqpixmap(ImageQt.toqpixmap(expected))
result = ImageQt.fromqpixmap(ImageQt.toqpixmap(expected)) # Qt saves all pixmaps as rgb
# Qt saves all pixmaps as rgb assert_image_equal(result, expected.convert("RGB"))
assert_image_equal(result, expected.convert("RGB"))
def test_sanity(self):
for mode in ("1", "RGB", "RGBA", "L", "P"): def test_sanity(qpixmap_app):
self.roundtrip(hopper(mode)) for mode in ("1", "RGB", "RGBA", "L", "P"):
roundtrip(hopper(mode))

View File

@ -1,7 +1,9 @@
from PIL import Image, ImageQt from PIL import Image, ImageQt
from .helper import PillowTestCase, assert_image_equal, hopper from .helper import assert_image_equal, hopper
from .test_imageqt import PillowQtTestCase from .test_imageqt import skip_if_qt_is_not_installed
pytestmark = skip_if_qt_is_not_installed()
if ImageQt.qt_is_installed: if ImageQt.qt_is_installed:
from PIL.ImageQt import QImage from PIL.ImageQt import QImage
@ -14,43 +16,43 @@ if ImageQt.qt_is_installed:
from PySide2.QtWidgets import QWidget, QHBoxLayout, QLabel, QApplication from PySide2.QtWidgets import QWidget, QHBoxLayout, QLabel, QApplication
class TestToQImage(PillowQtTestCase, PillowTestCase): def test_sanity(tmp_path):
def test_sanity(self): for mode in ("RGB", "RGBA", "L", "P", "1"):
for mode in ("RGB", "RGBA", "L", "P", "1"): src = hopper(mode)
src = hopper(mode) data = ImageQt.toqimage(src)
data = ImageQt.toqimage(src)
assert isinstance(data, QImage) assert isinstance(data, QImage)
assert not data.isNull() assert not data.isNull()
# reload directly from the qimage # reload directly from the qimage
rt = ImageQt.fromqimage(data) rt = ImageQt.fromqimage(data)
if mode in ("L", "P", "1"): if mode in ("L", "P", "1"):
assert_image_equal(rt, src.convert("RGB")) assert_image_equal(rt, src.convert("RGB"))
else: else:
assert_image_equal(rt, src) assert_image_equal(rt, src)
if mode == "1": if mode == "1":
# BW appears to not save correctly on QT4 and QT5 # BW appears to not save correctly on QT4 and QT5
# kicks out errors on console: # kicks out errors on console:
# libpng warning: Invalid color type/bit depth combination # libpng warning: Invalid color type/bit depth combination
# in IHDR # in IHDR
# libpng error: Invalid IHDR data # libpng error: Invalid IHDR data
continue continue
# Test saving the file # Test saving the file
tempfile = self.tempfile("temp_{}.png".format(mode)) tempfile = str(tmp_path / "temp_{}.png".format(mode))
data.save(tempfile) data.save(tempfile)
# Check that it actually worked. # Check that it actually worked.
with Image.open(tempfile) as reloaded: with Image.open(tempfile) as reloaded:
assert_image_equal(reloaded, src) assert_image_equal(reloaded, src)
def test_segfault(self):
app = QApplication([]) def test_segfault():
ex = Example() app = QApplication([])
assert app # Silence warning ex = Example()
assert ex # Silence warning assert app # Silence warning
assert ex # Silence warning
if ImageQt.qt_is_installed: if ImageQt.qt_is_installed:

View File

@ -1,20 +1,22 @@
import pytest
from PIL import ImageQt from PIL import ImageQt
from .helper import PillowTestCase, hopper from .helper import hopper
from .test_imageqt import PillowQPixmapTestCase from .test_imageqt import qpixmap_app, skip_if_qt_is_not_installed
if ImageQt.qt_is_installed: if ImageQt.qt_is_installed:
from PIL.ImageQt import QPixmap from PIL.ImageQt import QPixmap
pytestmark = skip_if_qt_is_not_installed()
class TestToQPixmap(PillowQPixmapTestCase, PillowTestCase):
def test_sanity(self):
for mode in ("1", "RGB", "RGBA", "L", "P"):
data = ImageQt.toqpixmap(hopper(mode))
assert isinstance(data, QPixmap) def test_sanity(qpixmap, tmp_path):
assert not data.isNull() for mode in ("1", "RGB", "RGBA", "L", "P"):
data = ImageQt.toqpixmap(hopper(mode))
# Test saving the file assert isinstance(data, QPixmap)
tempfile = self.tempfile("temp_{}.png".format(mode)) assert not data.isNull()
data.save(tempfile)
# Test saving the file
tempfile = str(tmp_path / "temp_{}.png".format(mode))
data.save(tempfile)