Merge pull request #7 from jovanovicisidora/branch_deekshu

Deekshu's Merge to Main
This commit is contained in:
Isidora Jovanovic 2024-06-27 01:11:51 +02:00 committed by GitHub
commit 86db022d48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 153 additions and 130 deletions

Binary file not shown.

View File

@ -1,64 +0,0 @@
import unittest
from PIL import Image
import unittest
class TestFromBytes(unittest.TestCase):
def test_frombytes(self):
# Test case 1: Empty bytes
data = b""
image = Image.frombytes("RGB", (0, 0), data)
self.assertEqual(image.size, (0, 0))
# Test case 2: Non-empty bytes
data = b"\x00\x00\xFF\xFF\x00\x00"
image = Image.frombytes("RGB", (2, 1), data)
self.assertEqual(image.size, (2, 1))
self.assertEqual(image.getpixel((0, 0)), (0, 0, 255))
self.assertEqual(image.getpixel((1, 0)), (255, 0, 0))
# Test case 3: Invalid mode
data = b"\x00\x00\xFF\xFF\x00\x00"
with self.assertRaises(ValueError):
Image.frombytes("RGBA", (2, 1), data)
# Test case 4: Non-RGB mode
data = b"\x00\x00\xFF\xFF\x00\x00"
image = Image.frombytes("L", (2, 1), data)
self.assertEqual(image.size, (2, 1))
self.assertEqual(image.getpixel((0, 0)), 0)
# self.assertEqual(image.getpixel((1, 0)), 255)
# Test case 5: Zero width
data = b""
image = Image.frombytes("RGB", (0, 1), data)
self.assertEqual(image.size, (0, 1))
# Test case 6: Zero height
data = b""
image = Image.frombytes("RGB", (1, 0), data)
self.assertEqual(image.size, (1, 0))
# Test case 7: s[0] < 0
data = b"\x00\x00\xFF\xFF\x00\x00"
s = (-1, 1)
with self.assertRaises(ValueError):
Image.frombytes("RGB", s, data)
# Test case 8: s[1] == 0
data = b"\x00\x00\xFF\xFF\x00\x00"
s = (2, 0)
# with self.assertRaises(ValueError):
# Image.frombytes("RGB", s, data)
# Test case 5: Different size
data = b"\x00\x00\xFF\xFF\x00\x00\xFF\xFF\x00\x00"
image = Image.frombytes("RGB", (3, 1), data)
self.assertEqual(image.size, (3, 1))
self.assertEqual(image.getpixel((0, 0)), (0, 0, 255))
self.assertEqual(image.getpixel((1, 0)), (255, 0, 0))
# self.assertEqual(image.getpixel((2, 0)), (255, 0, 0))
if __name__ == "__main__":
unittest.main()

View File

@ -39,7 +39,6 @@ HAVE_PROFILE = os.path.exists(SRGB)
def setup_module() -> None:
try:
from PIL import ImageCms
# need to hit getattr to trigger the delayed import error
ImageCms.core.profile_open
except ImportError as v:
@ -699,3 +698,37 @@ def test_deprecation() -> None:
assert ImageCms.VERSION == "1.0.0 pil"
with pytest.warns(DeprecationWarning):
assert isinstance(ImageCms.FLAGS, dict)
def test_buildTransform_flags_non_integer():
with pytest.raises(ImageCms.PyCMSError):
ImageCms.buildTransform(
inputProfile="path/to/input/profile",
outputProfile="path/to/output/profile",
inMode="RGB",
outMode="CMYK",
renderingIntent=ImageCms.Intent.PERCEPTUAL,
flags=123
)
def test_buildTransform_flags_invalid():
with pytest.raises(ImageCms.PyCMSError):
ImageCms.buildTransform(
inputProfile="path/to/input/profile",
outputProfile="path/to/output/profile",
inMode="RGB",
outMode="CMYK",
renderingIntent=ImageCms.Intent.PERCEPTUAL,
flags=999999
)
def test_rendering_intent_non_integer():
with pytest.raises(ImageCms.PyCMSError) as exc_info:
ImageCms.buildTransform(
inputProfile="path/to/input/profile",
outputProfile="path/to/output/profile",
inMode="RGB",
outMode="CMYK",
renderingIntent="not an integer",
flags=0
)
assert str(exc_info.value) == "renderingIntent must be an integer between 0 and 3"

View File

@ -215,19 +215,44 @@ class MockPyDecoder(ImageFile.PyDecoder):
class MockPyEncoder(ImageFile.PyEncoder):
last: MockPyEncoder | None
last = None
def __init__(self, mode: str, *args: Any) -> None:
super().__init__(mode, *args)
self._pushes_fd = False
self.cleanup_called = False
MockPyEncoder.last = self
super().__init__(mode, *args)
def encode(self, buffer):
# Simulate encoding
if buffer is None:
raise NotImplementedError
return 1, 1, b""
def cleanup(self) -> None:
self.cleanup_called = True
def test_encode_to_file() -> None:
encoder = MockPyEncoder("RGBA")
with pytest.raises(NotImplementedError):
encoder.encode_to_file(None, None)
encoder._pushes_fd = True
with pytest.raises(NotImplementedError):
encoder.encode_to_file(None, None)
buffer = BytesIO(b"\x00" * 10)
encoder._pushes_fd = False
encoder.encode = lambda buffer: (1, 1, b"")
try:
encoder.encode_to_file(buffer, None)
except NotImplementedError:
pass
encoder.encode = lambda buffer: (_ for _ in ()).throw(NotImplementedError)
with pytest.raises(NotImplementedError):
encoder.encode_to_file(buffer, None)
xoff, yoff, xsize, ysize = 10, 20, 100, 100

View File

@ -1,25 +1,25 @@
from __future__ import annotations
import pytest
import tkinter as tk
from unittest import mock
from PIL import Image
from PIL import ImageTk
from unittest.mock import patch
from .helper import assert_image_equal, hopper
TK_MODES = ("1", "L", "P", "RGB", "RGBA")
try:
import tkinter as tk
from PIL import ImageTk
dir(ImageTk)
HAS_TK = True
except (OSError, ImportError):
# Skipped via pytestmark
HAS_TK = False
TK_MODES = ("1", "L", "P", "RGB", "RGBA")
pytestmark = pytest.mark.skipif(not HAS_TK, reason="Tk not installed")
@ -27,7 +27,6 @@ def setup_module() -> None:
try:
# setup tk
tk.Frame()
# root = tk.Tk()
except RuntimeError as v:
pytest.skip(f"RuntimeError: {v}")
except tk.TclError as v:
@ -102,3 +101,5 @@ def test_bitmapimage() -> None:
# reloaded = ImageTk.getimage(im_tk)
# assert_image_equal(reloaded, im)

View File

@ -1,26 +1,26 @@
import pytest
from PIL import PdfParser
def test_delitem_new_entries():
parser = PdfParser.XrefTable()
parser.new_entries["test_key"] = ("value", 0)
del parser["test_key"]
assert "test_key" not in parser.new_entries
assert parser.deleted_entries["test_key"] == 1
def test_delitem_deleted_entries():
parser = PdfParser.XrefTable()
parser.deleted_entries["test_key"] = 0
del parser["test_key"]
assert parser.deleted_entries["test_key"] == 0
def test_delitem_nonexistent_key():
parser = PdfParser.XrefTable()
with pytest.raises(IndexError):
import pytest
from PIL import PdfParser
def test_delitem_new_entries():
parser = PdfParser.XrefTable()
parser.new_entries["test_key"] = ("value", 0)
del parser["test_key"]
assert "test_key" not in parser.new_entries
assert parser.deleted_entries["test_key"] == 1
def test_delitem_deleted_entries():
parser = PdfParser.XrefTable()
parser.deleted_entries["test_key"] = 0
del parser["test_key"]
assert parser.deleted_entries["test_key"] == 0
def test_delitem_nonexistent_key():
parser = PdfParser.XrefTable()
with pytest.raises(IndexError):
del parser["nonexistent_key"]

View File

@ -7,19 +7,19 @@ from PIL import PdfParser
from PIL import SpiderImagePlugin
from PIL import MpegImagePlugin
from PIL import ImageCms
from PIL import McIdasImagePlugin
from PIL import ImageFile
pytest_plugins = ["Tests.helper"]
def calculate_coverage(test_name):
all_branches = {
"branches1": Image.branches,
"branches2": PdfParser.XrefTable.branches,
"branches3": SpiderImagePlugin.branches,
"branches4": MpegImagePlugin.BitStream.branches,
"branches5": ImageCms.ImageCmsProfile.branches,
"branches6": McIdasImagePlugin.McIdasImageFile.branches,
"branches1": Image.branches, # duru
"branches2": PdfParser.XrefTable.branches, # duru
"branches3": SpiderImagePlugin.branches, # isidora
"branches4": MpegImagePlugin.BitStream.branches, # isidora
"branches5": ImageCms.branches, # deekshu
"branches6": ImageFile.PyEncoder.branches, # deekshu
# Add more
}
@ -54,4 +54,3 @@ def pytest_sessionfinish(session, exitstatus):
coverage = calculate_coverage(test_name)
print("\nBRANCH COVERAGE for", test_name, ":", coverage, "%\n")

View File

@ -29,6 +29,15 @@ from . import Image, __version__
from ._deprecate import deprecate
from ._typing import SupportsRead
branches = {
"1": False,
"2": False,
"3": False,
"4": False,
"5": False,
"6": False,
}
try:
from . import _imagingcms as core
except ImportError as ex:
@ -237,17 +246,6 @@ _FLAGS = {
class ImageCmsProfile:
branches = {
"1": False,
"2": False,
"3": False,
"4": False,
"5": False,
"6": False,
"7": False,
"8": False,
}
def __init__(self, profile: str | SupportsRead[bytes] | core.CmsProfile) -> None:
"""
:param profile: Either a string representing a filename,
@ -257,28 +255,21 @@ class ImageCmsProfile:
"""
if isinstance(profile, str):
ImageCmsProfile.branches["1"] = True
if sys.platform == "win32":
ImageCmsProfile.branches["2"] = True
profile_bytes_path = profile.encode()
try:
ImageCmsProfile.branches["3"] = True
profile_bytes_path.decode("ascii")
except UnicodeDecodeError:
ImageCmsProfile.branches["4"] = True
with open(profile, "rb") as f:
ImageCmsProfile.branches["5"] = True
self._set(core.profile_frombytes(f.read()))
return
self._set(core.profile_open(profile), profile)
elif hasattr(profile, "read"):
ImageCmsProfile.branches["6"] = True
self._set(core.profile_frombytes(profile.read()))
elif isinstance(profile, core.CmsProfile):
ImageCmsProfile.branches["7"] = True
self._set(profile)
else:
ImageCmsProfile.branches["8"] = True
msg = "Invalid type for Profile" # type: ignore[unreachable]
raise TypeError(msg)
@ -582,22 +573,28 @@ def buildTransform(
"""
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
branches["1"] = True
msg = "renderingIntent must be an integer between 0 and 3"
raise PyCMSError(msg)
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
branches["2"] = True
msg = f"flags must be an integer between 0 and {_MAX_FLAG}"
raise PyCMSError(msg)
try:
branches["3"] = True
if not isinstance(inputProfile, ImageCmsProfile):
branches["4"] = True
inputProfile = ImageCmsProfile(inputProfile)
if not isinstance(outputProfile, ImageCmsProfile):
branches["5"] = True
outputProfile = ImageCmsProfile(outputProfile)
return ImageCmsTransform(
inputProfile, outputProfile, inMode, outMode, renderingIntent, flags=flags
)
except (OSError, TypeError, ValueError) as v:
branches["6"] = True
raise PyCMSError(v) from v

View File

@ -39,6 +39,7 @@ from . import Image
from ._deprecate import deprecate
from ._util import is_path
MAXBLOCK = 65536
SAFEBLOCK = 1024 * 1024
@ -750,6 +751,11 @@ class PyDecoder(PyCodec):
class PyEncoder(PyCodec):
branches = {
"1": False,
"2": False,
}
"""
Python implementation of a format encoder. Override this class and
add the decoding logic in the :meth:`encode` method.
@ -801,7 +807,9 @@ class PyEncoder(PyCodec):
"""
errcode = 0
while errcode == 0:
PyEncoder.branches["1"] = True
status, errcode, buf = self.encode(bufsize)
if status > 0:
PyEncoder.branches["2"] = True
fh.write(buf[status:])
return errcode

View File

@ -21,7 +21,6 @@ import struct
from . import Image, ImageFile
def _accept(prefix: bytes) -> bool:
return prefix[:8] == b"\x00\x00\x00\x00\x00\x00\x00\x04"

25
src/PIL/test_ImageFile.py Normal file
View File

@ -0,0 +1,25 @@
from io import BytesIO
import pytest
from PIL import ImageFile
def test_encode_to_file_branches():
# Create a mock file object
mock_file = io.BytesIO()
# Create a PyEncoder instance
encoder = ImageFile.PyEncoder("RGB")
# Set the branches dictionary to False to ensure both branches are covered
encoder.branches = {"1": False, "2": False}
# Call the encode_to_file method
errcode = encoder.encode_to_file(mock_file, 1024)
# Check that the branches dictionary has been updated
assert encoder.branches["1"] is True
assert encoder.branches["2"] is True
# Check that the error code is 0, indicating successful encoding
assert errcode == 0
mock_file = BytesIO()