diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml new file mode 100644 index 0000000..3e92024 --- /dev/null +++ b/.github/workflows/python-package.yml @@ -0,0 +1,39 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Python package + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install setuptools wheel typing pillow numpy requests + python -m pip install -e . + python -m pip install ruff pytest + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Lint with ruff + run: | + # Run Ruff for linting + ruff check . + - name: Test with pytest + run: | + pytest diff --git a/tests/test_functionalities.py b/tests/test_functionalities.py new file mode 100644 index 0000000..a79c5dd --- /dev/null +++ b/tests/test_functionalities.py @@ -0,0 +1,123 @@ +import unittest +import os +import tempfile +import numpy as np +from PIL import Image +import base64 +from unittest.mock import patch, MagicMock + +from loadimg import load_img +from loadimg.utils import starts_with, download_image, isBase64 + + +class TestImageLoader(unittest.TestCase): + def setUp(self): + self.temp_dir = tempfile.TemporaryDirectory() + self.sample_image_path = os.path.join(self.temp_dir.name, "sample.png") + self.sample_image = Image.new("RGB", (100, 100), color="red") + self.sample_image.save(self.sample_image_path) + self.sample_numpy_array = np.array(self.sample_image) + + with open(self.sample_image_path, "rb") as image_file: + self.sample_base64 = base64.b64encode(image_file.read()).decode("utf-8") + + def tearDown(self): + self.temp_dir.cleanup() + + def test_load_img_from_file(self): + img = load_img(self.sample_image_path, output_type="pil") + self.assertIsInstance(img, Image.Image) + + img = load_img(self.sample_image_path, output_type="numpy") + self.assertIsInstance(img, np.ndarray) + + img = load_img(self.sample_image_path, output_type="str") + self.assertTrue(os.path.exists(img)) + + img = load_img(self.sample_image_path, output_type="base64") + self.assertTrue(img.startswith("data:image/png;base64,")) + + def test_load_img_from_base64(self): + img = load_img(f"data:image/png;base64,{self.sample_base64}", output_type="pil") + self.assertIsInstance(img, Image.Image) + + img = load_img( + f"data:image/png;base64,{self.sample_base64}", output_type="numpy" + ) + self.assertIsInstance(img, np.ndarray) + + img = load_img(f"data:image/png;base64,{self.sample_base64}", output_type="str") + self.assertTrue(os.path.exists(img)) + + img = load_img( + f"data:image/png;base64,{self.sample_base64}", output_type="base64" + ) + self.assertTrue(img.startswith("data:image/png;base64,")) + + def test_load_img_from_numpy(self): + img = load_img(self.sample_numpy_array, output_type="pil") + self.assertIsInstance(img, Image.Image) + + img = load_img(self.sample_numpy_array, output_type="numpy") + self.assertIsInstance(img, np.ndarray) + + img = load_img(self.sample_numpy_array, output_type="str") + self.assertTrue(os.path.exists(img)) + + img = load_img(self.sample_numpy_array, output_type="base64") + self.assertTrue(img.startswith("data:image/png;base64,")) + + def test_load_img_from_pil(self): + img = load_img(self.sample_image, output_type="pil") + self.assertIsInstance(img, Image.Image) + + img = load_img(self.sample_image, output_type="numpy") + self.assertIsInstance(img, np.ndarray) + + img = load_img(self.sample_image, output_type="str") + self.assertTrue(os.path.exists(img)) + + img = load_img(self.sample_image, output_type="base64") + self.assertTrue(img.startswith("data:image/png;base64,")) + + @patch("requests.get") + def test_load_img_from_url(self, mock_get): + mock_response = MagicMock() + mock_response.content = open(self.sample_image_path, "rb").read() + mock_response.raise_for_status.return_value = None + mock_get.return_value = mock_response + + img = load_img("https://example.com/sample.png", output_type="pil") + self.assertIsInstance(img, Image.Image) + + img = load_img("https://example.com/sample.png", output_type="numpy") + self.assertIsInstance(img, np.ndarray) + + img = load_img("https://example.com/sample.png", output_type="str") + self.assertTrue(os.path.exists(img)) + + img = load_img("https://example.com/sample.png", output_type="base64") + self.assertTrue(img.startswith("data:image/png;base64,")) + + def test_starts_with(self): + self.assertTrue(starts_with("github", "https://github.com/user/repo")) + self.assertTrue(starts_with("github", "github.com/user/repo")) + self.assertFalse(starts_with("github", "https://example.com")) + + @patch("requests.get") + def test_download_image(self, mock_get): + mock_response = MagicMock() + mock_response.content = open(self.sample_image_path, "rb").read() + mock_response.raise_for_status.return_value = None + mock_get.return_value = mock_response + + img = download_image("https://example.com/sample.png") + self.assertIsInstance(img, Image.Image) + + def test_isBase64(self): + self.assertTrue(isBase64(self.sample_base64)) + self.assertFalse(isBase64("not a base64 string")) + + +if __name__ == "__main__": + unittest.main()