From 266c2c9a072bf3289fd7f2d75278b7d59528378c Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sat, 24 Dec 2022 10:27:09 +0100 Subject: package restructuring: base * Reader and Extractor to respective reader/extractor modules * ReaderBuilder to reader module * ExtractorBuilder to extractor module * Loading module in utils (safe_load, unpack_name) * Pipeline and PipelineBuilder to lib module * errors to utils * documentation: "standard import" and "external import" --- test/reader/test_base.py | 45 +++++++++++++++++++++++++++++++++++++ test/reader/test_builder.py | 54 +++++++++++++++++++++++++++++++++++++++++++++ test/reader/test_stat.py | 4 ++-- 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 test/reader/test_base.py create mode 100644 test/reader/test_builder.py (limited to 'test/reader') diff --git a/test/reader/test_base.py b/test/reader/test_base.py new file mode 100644 index 0000000..41f4c29 --- /dev/null +++ b/test/reader/test_base.py @@ -0,0 +1,45 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import unittest + +# objects to test +from bsie.reader import Reader + + +## code ## + +class StubReader(Reader): + def __call__(self, path): + raise NotImplementedError() + +class StubSub(StubReader): + pass + +class TestReader(unittest.TestCase): + def test_essentials(self): + ext = StubReader() + self.assertEqual(str(ext), 'StubReader') + self.assertEqual(repr(ext), 'StubReader()') + self.assertEqual(ext, StubReader()) + self.assertEqual(hash(ext), hash(StubReader())) + + sub = StubSub() + self.assertEqual(str(sub), 'StubSub') + self.assertEqual(repr(sub), 'StubSub()') + self.assertEqual(sub, StubSub()) + self.assertEqual(hash(sub), hash(StubSub())) + self.assertNotEqual(ext, sub) + self.assertNotEqual(hash(ext), hash(sub)) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/test_builder.py b/test/reader/test_builder.py new file mode 100644 index 0000000..92e9edc --- /dev/null +++ b/test/reader/test_builder.py @@ -0,0 +1,54 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import unittest + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader import ReaderBuilder + + +## code ## + +class TestReaderBuilder(unittest.TestCase): + def test_build(self): + builder = ReaderBuilder({'bsie.reader.path.Path': {}}) + # build configured reader + cls = builder.build('bsie.reader.path.Path') + import bsie.reader.path + self.assertIsInstance(cls, bsie.reader.path.Path) + # build unconfigured reader + cls = builder.build('bsie.reader.stat.Stat') + import bsie.reader.stat + self.assertIsInstance(cls, bsie.reader.stat.Stat) + # re-build previous reader (test cache) + self.assertEqual(cls, builder.build('bsie.reader.stat.Stat')) + # test invalid + self.assertRaises(TypeError, builder.build, 123) + self.assertRaises(TypeError, builder.build, None) + self.assertRaises(ValueError, builder.build, '') + self.assertRaises(ValueError, builder.build, 'Path') + self.assertRaises(errors.BuilderError, builder.build, 'path.Path') + # invalid config + builder = ReaderBuilder({'bsie.reader.stat.Stat': dict(foo=123)}) + self.assertRaises(errors.BuilderError, builder.build, 'bsie.reader.stat.Stat') + builder = ReaderBuilder({'bsie.reader.stat.Stat': 123}) + self.assertRaises(TypeError, builder.build, 'bsie.reader.stat.Stat') + # no instructions + builder = ReaderBuilder({}) + cls = builder.build('bsie.reader.stat.Stat') + self.assertIsInstance(cls, bsie.reader.stat.Stat) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/test_stat.py b/test/reader/test_stat.py index d12ad9c..fd9fdcd 100644 --- a/test/reader/test_stat.py +++ b/test/reader/test_stat.py @@ -4,12 +4,12 @@ Part of the bsie test suite. A copy of the license is provided with the project. Author: Matthias Baumgartner, 2022 """ -# imports +# standard imports import os import unittest # bsie imports -from bsie.base import errors +from bsie.utils import errors # objects to test from bsie.reader.stat import Stat -- cgit v1.2.3 From 07219685d01f803dc46c8d5465fa542c1d822cb4 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sat, 24 Dec 2022 10:39:51 +0100 Subject: documentation: standard vs external import --- test/reader/test_path.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test/reader') diff --git a/test/reader/test_path.py b/test/reader/test_path.py index fd7bc5a..95e447f 100644 --- a/test/reader/test_path.py +++ b/test/reader/test_path.py @@ -4,7 +4,7 @@ Part of the bsie test suite. A copy of the license is provided with the project. Author: Matthias Baumgartner, 2022 """ -# imports +# standard imports import unittest # objects to test -- cgit v1.2.3 From 17f03ae3d3dc53fe973f37fe4dea4a831b4f97d7 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sat, 24 Dec 2022 16:06:16 +0100 Subject: ReaderChain and image reader --- test/reader/image/__init__.py | 0 test/reader/image/load_nef.py | 28 ++++++++++++ test/reader/image/test_image.py | 51 ++++++++++++++++++++++ test/reader/image/test_pillow.py | 44 +++++++++++++++++++ test/reader/image/test_raw_image.py | 50 +++++++++++++++++++++ test/reader/image/testimage.jpg | Bin 0 -> 518 bytes test/reader/test_chain.py | 85 ++++++++++++++++++++++++++++++++++++ 7 files changed, 258 insertions(+) create mode 100644 test/reader/image/__init__.py create mode 100644 test/reader/image/load_nef.py create mode 100644 test/reader/image/test_image.py create mode 100644 test/reader/image/test_pillow.py create mode 100644 test/reader/image/test_raw_image.py create mode 100644 test/reader/image/testimage.jpg create mode 100644 test/reader/test_chain.py (limited to 'test/reader') diff --git a/test/reader/image/__init__.py b/test/reader/image/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/reader/image/load_nef.py b/test/reader/image/load_nef.py new file mode 100644 index 0000000..5ba0adc --- /dev/null +++ b/test/reader/image/load_nef.py @@ -0,0 +1,28 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os + +# external imports +import requests + +# constants +IMAGE_URL = 'http://igsor.net/eik7AhvohghaeN5.nef' + +## code ## + +def get(): + """Download a raw test image.""" + target = os.path.join(os.path.dirname(__file__), 'testimage.nef') + if not os.path.exists(target): + with open(target, 'wb') as ofile: + ans = requests.get(IMAGE_URL) + ofile.write(ans.content) + + + +## EOF ## diff --git a/test/reader/image/test_image.py b/test/reader/image/test_image.py new file mode 100644 index 0000000..c60ca75 --- /dev/null +++ b/test/reader/image/test_image.py @@ -0,0 +1,51 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import importlib +import os +import unittest + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader.image import Image + + +## code ## + +class TestImage(unittest.TestCase): + def setUp(self): + importlib.import_module(__package__ + '.load_nef').get() + + def test_construct(self): + image = Image({}) + self.assertIsInstance(image, Image) + self.assertEqual(len(image._children), 2) + + def test_call(self): + image = Image({}) + # call returns raw image + img = image(os.path.join(os.path.dirname(__file__), 'testimage.nef')) + self.assertEqual(img.size, (6016, 4016)) # FIXME: change when image was replaced + img.close() + # call returns jpeg image + img = image(os.path.join(os.path.dirname(__file__), 'testimage.jpg')) + self.assertEqual(img.size, (1, 1)) + img.close() + # call raises error if file cannot be read + self.assertRaises(errors.ReaderError, image, + os.path.join(os.path.dirname(__file__), 'invalid.nef')) + self.assertRaises(errors.ReaderError, image, + os.path.join(os.path.dirname(__file__), 'invalid.jpg')) + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/image/test_pillow.py b/test/reader/image/test_pillow.py new file mode 100644 index 0000000..8abf5c1 --- /dev/null +++ b/test/reader/image/test_pillow.py @@ -0,0 +1,44 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os +import unittest + +# external imports +import PIL.Image + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader.image._pillow import PillowImage + + +## code ## + +class TestPillowImage(unittest.TestCase): + def test_call(self): + rdr = PillowImage() + # returns PIL image + img = rdr(os.path.join(os.path.dirname(__file__), 'testimage.jpg')) + self.assertEqual(img.size, (1, 1)) + self.assertEqual(img.getdata().getpixel((0, 0)), (0, 0, 0)) + img.close() + # raises exception when image cannot be read + self.assertRaises(errors.ReaderError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.jpg')) + # NOTE: PIL can actually read raw image files (returns the thumbnail) + #self.assertRaises(errors.ReaderError, rdr, + # os.path.join(os.path.dirname(__file__), 'testimage.nef')) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/image/test_raw_image.py b/test/reader/image/test_raw_image.py new file mode 100644 index 0000000..3d5f887 --- /dev/null +++ b/test/reader/image/test_raw_image.py @@ -0,0 +1,50 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import importlib +import os +import unittest + +# external imports +import PIL.Image + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader.image._raw import RawImage + + +## code ## + +class TestRawImage(unittest.TestCase): + def setUp(self): + importlib.import_module(__package__ + '.load_nef').get() + + def test_call(self): + rdr = RawImage() + # returns PIL image + img = rdr(os.path.join(os.path.dirname(__file__), 'testimage.nef')) + self.assertEqual(img.size, (6016, 4016)) # FIXME: change when image was replaced + #self.assertEqual(img.size, (1, 1)) + #self.assertEqual(img.getdata().getpixel((0, 0)), (0, 0, 0)) + img.close() + # raises exception when image cannot be read + self.assertRaises(errors.ReaderError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.nef')) + self.assertRaises(errors.ReaderError, rdr, + os.path.join(os.path.dirname(__file__), 'testimage.jpg')) + + + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/image/testimage.jpg b/test/reader/image/testimage.jpg new file mode 100644 index 0000000..ea7af63 Binary files /dev/null and b/test/reader/image/testimage.jpg differ diff --git a/test/reader/test_chain.py b/test/reader/test_chain.py new file mode 100644 index 0000000..901faa1 --- /dev/null +++ b/test/reader/test_chain.py @@ -0,0 +1,85 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import logging +import os +import unittest + +# bsie imports +from bsie.utils import errors +import bsie.reader.path +import bsie.reader.stat + +# objects to test +from bsie.reader.chain import ReaderChain + + +## code ## + +class TestReaderChain(unittest.TestCase): + def test_construct(self): + # subreaders are built + chain = ReaderChain(['bsie.reader.stat.Stat', 'bsie.reader.path.Path'], {}) + self.assertIsInstance(chain, ReaderChain) + self.assertEqual(chain._children, + (bsie.reader.stat.Stat(), bsie.reader.path.Path())) + # subreaders that failed to build are omitted + with self.assertLogs(logging.getLogger('bsie.reader.chain'), logging.WARNING): + chain = ReaderChain(['bsie.reader.stat.Stat', 'bsie.reader.invalid.Invalid'], {}) + self.assertEqual(chain._children, (bsie.reader.stat.Stat(), )) + with self.assertLogs(logging.getLogger('bsie.reader.chain'), logging.WARNING): + chain = ReaderChain(['bsie.reader.stat.Stat', 'bsie.reader.path.Invalid'], {}) + self.assertEqual(chain._children, (bsie.reader.stat.Stat(), )) + # warning is issued if there are no subreaders + with self.assertLogs(logging.getLogger('bsie.reader.chain'), logging.WARNING): + chain = ReaderChain([], {}) + self.assertEqual(chain._children, tuple()) + + def test_essentials(self): + chain = ReaderChain(['bsie.reader.stat.Stat', 'bsie.reader.path.Path'], {}) + # identity + self.assertEqual(chain, chain) + self.assertEqual(hash(chain), hash(chain)) + # comparison works across instances + self.assertEqual(chain, + ReaderChain(['bsie.reader.stat.Stat', 'bsie.reader.path.Path'], {})) + self.assertEqual(hash(chain), + hash(ReaderChain(['bsie.reader.stat.Stat', 'bsie.reader.path.Path'], {}))) + # comparison respects subreaders + self.assertNotEqual(hash(chain), + hash(ReaderChain(['bsie.reader.path.Path'], {}))) + self.assertNotEqual(hash(chain), + hash(ReaderChain(['bsie.reader.path.Path'], {}))) + # comparison respects subreader order + self.assertNotEqual(chain, + ReaderChain(['bsie.reader.path.Path', 'bsie.reader.stat.Stat'], {})) + self.assertNotEqual(hash(chain), + hash(ReaderChain(['bsie.reader.path.Path', 'bsie.reader.stat.Stat'], {}))) + # string representation + self.assertEqual(str(chain), 'ReaderChain(Stat, Path)') + self.assertEqual(repr(chain), 'ReaderChain((Stat(), Path()))') + + def test_call(self): + chain = ReaderChain(['bsie.reader.stat.Stat', 'bsie.reader.path.Path'], {}) + # chain first probes first child + self.assertEqual(chain(__file__), os.stat(__file__)) + # chain probes second child if first one failes + self.assertEqual(chain(''), '') + self.assertEqual(chain('missing-file'), 'missing-file') + + # chain raises a ReaderError if childs were exhausted + chain = ReaderChain(['bsie.reader.stat.Stat'], {}) + # chain probes second child if first one failes + self.assertRaises(errors.ReaderError, chain, '') + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## -- cgit v1.2.3 From 3f93be488638fdf6668e0e03e2b1634bb969ca80 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Mon, 16 Jan 2023 15:39:16 +0100 Subject: random fixes --- test/reader/image/test_image.py | 5 ++++- test/reader/image/test_raw_image.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'test/reader') diff --git a/test/reader/image/test_image.py b/test/reader/image/test_image.py index c60ca75..26f6a93 100644 --- a/test/reader/image/test_image.py +++ b/test/reader/image/test_image.py @@ -20,7 +20,10 @@ from bsie.reader.image import Image class TestImage(unittest.TestCase): def setUp(self): - importlib.import_module(__package__ + '.load_nef').get() + if __package__ is None or __package__ == '': # direct call or local discovery + importlib.import_module('load_nef', __package__).get() + else: # parent discovery + importlib.import_module('.load_nef', __package__).get() def test_construct(self): image = Image({}) diff --git a/test/reader/image/test_raw_image.py b/test/reader/image/test_raw_image.py index 3d5f887..ba21b5a 100644 --- a/test/reader/image/test_raw_image.py +++ b/test/reader/image/test_raw_image.py @@ -23,7 +23,10 @@ from bsie.reader.image._raw import RawImage class TestRawImage(unittest.TestCase): def setUp(self): - importlib.import_module(__package__ + '.load_nef').get() + if __package__ is None or __package__ == '': # direct call or local discovery + importlib.import_module('load_nef', __package__).get() + else: # parent discovery + importlib.import_module('.load_nef', __package__).get() def test_call(self): rdr = RawImage() -- cgit v1.2.3 From 482235a8229261fa905f73ce167982bca57ab3e6 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Wed, 8 Feb 2023 19:21:28 +0100 Subject: preview reader --- test/reader/preview/__init__.py | 0 test/reader/preview/invalid.foo | 0 test/reader/preview/invalid.jpg | 0 test/reader/preview/load_nef.py | 28 ++++++++++++ test/reader/preview/test_pg.py | 82 ++++++++++++++++++++++++++++++++++++ test/reader/preview/test_pillow.py | 50 ++++++++++++++++++++++ test/reader/preview/test_preview.py | 77 +++++++++++++++++++++++++++++++++ test/reader/preview/test_rawpy.py | 59 ++++++++++++++++++++++++++ test/reader/preview/test_utils.py | 44 +++++++++++++++++++ test/reader/preview/testfile.pdf | Bin 0 -> 7295 bytes test/reader/preview/testimage.jpg | Bin 0 -> 6476 bytes 11 files changed, 340 insertions(+) create mode 100644 test/reader/preview/__init__.py create mode 100644 test/reader/preview/invalid.foo create mode 100644 test/reader/preview/invalid.jpg create mode 100644 test/reader/preview/load_nef.py create mode 100644 test/reader/preview/test_pg.py create mode 100644 test/reader/preview/test_pillow.py create mode 100644 test/reader/preview/test_preview.py create mode 100644 test/reader/preview/test_rawpy.py create mode 100644 test/reader/preview/test_utils.py create mode 100644 test/reader/preview/testfile.pdf create mode 100644 test/reader/preview/testimage.jpg (limited to 'test/reader') diff --git a/test/reader/preview/__init__.py b/test/reader/preview/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/reader/preview/invalid.foo b/test/reader/preview/invalid.foo new file mode 100644 index 0000000..e69de29 diff --git a/test/reader/preview/invalid.jpg b/test/reader/preview/invalid.jpg new file mode 100644 index 0000000..e69de29 diff --git a/test/reader/preview/load_nef.py b/test/reader/preview/load_nef.py new file mode 100644 index 0000000..5ba0adc --- /dev/null +++ b/test/reader/preview/load_nef.py @@ -0,0 +1,28 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os + +# external imports +import requests + +# constants +IMAGE_URL = 'http://igsor.net/eik7AhvohghaeN5.nef' + +## code ## + +def get(): + """Download a raw test image.""" + target = os.path.join(os.path.dirname(__file__), 'testimage.nef') + if not os.path.exists(target): + with open(target, 'wb') as ofile: + ans = requests.get(IMAGE_URL) + ofile.write(ans.content) + + + +## EOF ## diff --git a/test/reader/preview/test_pg.py b/test/reader/preview/test_pg.py new file mode 100644 index 0000000..e492cfa --- /dev/null +++ b/test/reader/preview/test_pg.py @@ -0,0 +1,82 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +from functools import partial +import os +import shutil +import tempfile +import unittest + +# external imports +import PIL.Image + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader.preview._pg import PreviewGeneratorReader + + +## code ## + +class TestPreviewGeneratorReader(unittest.TestCase): + def test_call(self): + rdr = PreviewGeneratorReader() + # inexistent file raises a ReaderError + self.assertRaises(errors.ReaderError, rdr, + os.path.join(os.path.dirname(__file__), 'missing.jpg')) + # unsupported file type raises an UnsupportedFileFormatError + self.assertRaises(errors.UnsupportedFileFormatError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.foo')) + # invalid file raises a ReaderError + self.assertRaises(errors.ReaderError, + rdr(os.path.join(os.path.dirname(__file__), 'invalid.jpg')), 100) + + # proper file produces a generator + gen = rdr(os.path.join(os.path.dirname(__file__), 'testimage.jpg')) + self.assertIsInstance(gen, partial) + # generator produces an image + img = gen(10) + self.assertIsInstance(img, PIL.Image.Image) + self.assertEqual(img.size, (10, 10)) + self.assertEqual(sum(img.getdata()), 0) + # cleanup + img.close() + + # preview generator can also extract data from non-image files + gen = rdr(os.path.join(os.path.dirname(__file__), 'testfile.pdf')) + self.assertIsInstance(gen, partial) + # generator produces an image + img = gen(10) + self.assertIsInstance(img, PIL.Image.Image) + self.assertEqual(img.size, (8, 10)) + self.assertEqual(sum(img.getdata()), 20258) + # cleanup + img.close() + + # can define a cache dir + pg_dir = tempfile.mkdtemp(prefix='bsie-test') + self.assertTrue(os.path.exists(pg_dir)) + rdr = PreviewGeneratorReader(cache=pg_dir) + gen = rdr(os.path.join(os.path.dirname(__file__), 'testimage.jpg')) + img = gen(10) + self.assertIsInstance(img, PIL.Image.Image) + self.assertEqual(img.size, (10, 10)) + self.assertEqual(sum(img.getdata()), 0) + img.close() + del rdr + # cache dir still exists after instance deletion + self.assertTrue(os.path.exists(pg_dir)) + shutil.rmtree(pg_dir, ignore_errors=True) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/preview/test_pillow.py b/test/reader/preview/test_pillow.py new file mode 100644 index 0000000..ca38d89 --- /dev/null +++ b/test/reader/preview/test_pillow.py @@ -0,0 +1,50 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +from functools import partial +import os +import unittest + +# external imports +import PIL.Image + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader.preview._pillow import PillowPreviewReader + + +## code ## + +class TestPillowPreviewReader(unittest.TestCase): + def test_call(self): + rdr = PillowPreviewReader() + # raises exception when image cannot be read + self.assertRaises(errors.ReaderError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.jpg')) + # raises exception when image has invalid type + self.assertRaises(errors.UnsupportedFileFormatError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.foo')) + # proper file produces a generator + gen = rdr(os.path.join(os.path.dirname(__file__), 'testimage.jpg')) + self.assertIsInstance(gen, partial) + # generator produces an image + img = gen(10) + self.assertIsInstance(img, PIL.Image.Image) + self.assertEqual(img.size, (10, 10)) + self.assertEqual(sum(band for pix in img.getdata() for band in pix), 0) + # cleanup + img.close() + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/preview/test_preview.py b/test/reader/preview/test_preview.py new file mode 100644 index 0000000..fde610f --- /dev/null +++ b/test/reader/preview/test_preview.py @@ -0,0 +1,77 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +from functools import partial +import importlib +import os +import unittest + +# external imports +import PIL.Image + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader.preview import Preview + + +## code ## + +class TestPreview(unittest.TestCase): + def setUp(self): + if __package__ is None or __package__ == '': # direct call or local discovery + importlib.import_module('load_nef', __package__).get() + else: # parent discovery + importlib.import_module('.load_nef', __package__).get() + + def test_construct(self): + preview = Preview() + self.assertIsInstance(preview, Preview) + self.assertEqual(len(preview._children), 3) + + def test_call(self): + preview = Preview() + # call raises error if file cannot be read + self.assertRaises(errors.ReaderError, preview, + os.path.join(os.path.dirname(__file__), 'missing.jpg')) + self.assertRaises(errors.ReaderError, preview( + os.path.join(os.path.dirname(__file__), 'invalid.jpg')), 10) + self.assertRaises(errors.UnsupportedFileFormatError, preview, + os.path.join(os.path.dirname(__file__), 'invalid.foo')) + + # call returns raw preview + gen = preview(os.path.join(os.path.dirname(__file__), 'testimage.nef')) + img = gen(10) + self.assertIsInstance(img, PIL.Image.Image) + self.assertEqual(img.size, (10, 8)) + self.assertEqual(sum(band for pix in img.getdata() for band in pix), 25287) + img.close() + + # call returns jpeg image + gen = preview(os.path.join(os.path.dirname(__file__), 'testimage.jpg')) + img = gen(10) + self.assertIsInstance(img, PIL.Image.Image) + self.assertEqual(img.size, (10, 10)) + self.assertEqual(sum(band for pix in img.getdata() for band in pix), 0) + img.close() + + # preview generator can also extract data from non-image files + gen = preview(os.path.join(os.path.dirname(__file__), 'testfile.pdf')) + img = gen(10) + self.assertIsInstance(img, PIL.Image.Image) + self.assertEqual(img.size, (8, 10)) + self.assertEqual(sum(img.getdata()), 20258) + img.close() + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/preview/test_rawpy.py b/test/reader/preview/test_rawpy.py new file mode 100644 index 0000000..ed35f53 --- /dev/null +++ b/test/reader/preview/test_rawpy.py @@ -0,0 +1,59 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +from functools import partial +import importlib +import os +import unittest + +# external imports +import PIL.Image + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader.preview._rawpy import RawpyPreviewReader + + +## code ## + +class TestRawpyPreviewReader(unittest.TestCase): + def setUp(self): + if __package__ is None or __package__ == '': # direct call or local discovery + importlib.import_module('load_nef', __package__).get() + else: # parent discovery + importlib.import_module('.load_nef', __package__).get() + + def test_call(self): + rdr = RawpyPreviewReader() + # raises exception when image cannot be read + self.assertRaises(errors.ReaderError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.nef')) + # raises exception when image has invalid type + self.assertRaises(errors.UnsupportedFileFormatError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.jpg')) + self.assertRaises(errors.UnsupportedFileFormatError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.foo')) + # proper file produces a generator + gen = rdr(os.path.join(os.path.dirname(__file__), 'testimage.nef')) + self.assertIsInstance(gen, partial) + # generator produces an image + img = gen(10) + self.assertIsInstance(img, PIL.Image.Image) + self.assertEqual(img.size, (10, 7)) + self.assertEqual(sum(band for pix in img.getdata() for band in pix), 15269) + # cleanup + img.close() + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/preview/test_utils.py b/test/reader/preview/test_utils.py new file mode 100644 index 0000000..c10c38c --- /dev/null +++ b/test/reader/preview/test_utils.py @@ -0,0 +1,44 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os +import unittest + +# external imports +import PIL.Image + +# objects to test +from bsie.reader.preview.utils import resize + + +## code ## + +class TestUtils(unittest.TestCase): + + def test_resize(self): + img = PIL.Image.open(os.path.join(os.path.dirname(__file__), 'testimage.jpg')) + landscape = img.resize((100, 80)) + portrait = img.resize((80, 100)) + self.assertEqual(img.size, (100, 100)) + self.assertEqual(landscape.size, (100, 80)) + self.assertEqual(portrait.size, (80, 100)) + # resize can downscale + self.assertEqual(resize(img, 10).size, (10, 10)) + self.assertEqual(resize(img, 20).size, (20, 20)) + # resize can upscale + self.assertEqual(resize(img, 200).size, (200, 200)) + # aspect ratio is preserved + self.assertEqual(resize(landscape, 10).size, (10, 8)) + self.assertEqual(resize(portrait, 10).size, (8, 10)) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/preview/testfile.pdf b/test/reader/preview/testfile.pdf new file mode 100644 index 0000000..592d448 Binary files /dev/null and b/test/reader/preview/testfile.pdf differ diff --git a/test/reader/preview/testimage.jpg b/test/reader/preview/testimage.jpg new file mode 100644 index 0000000..4c2aca5 Binary files /dev/null and b/test/reader/preview/testimage.jpg differ -- cgit v1.2.3 From ec9105b690974b0246e36769506e735c4edf069a Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Wed, 1 Mar 2023 21:38:09 +0100 Subject: Exif data reader and extractor --- test/reader/test_exif.py | 48 +++++++++++++++++++++++++++++++++++++++++ test/reader/testimage_exif.jpg | Bin 0 -> 719 bytes 2 files changed, 48 insertions(+) create mode 100644 test/reader/test_exif.py create mode 100644 test/reader/testimage_exif.jpg (limited to 'test/reader') diff --git a/test/reader/test_exif.py b/test/reader/test_exif.py new file mode 100644 index 0000000..f1330da --- /dev/null +++ b/test/reader/test_exif.py @@ -0,0 +1,48 @@ +""" + +Part of the bsie test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# standard imports +import os +import unittest + +# bsie imports +from bsie.utils import errors + +# objects to test +from bsie.reader.exif import Exif + + +## code ## + +class TestExif(unittest.TestCase): + def test_call(self): + rdr = Exif() + # discards non-image files + self.assertRaises(errors.UnsupportedFileFormatError, rdr, 'invalid.doc') + # raises on invalid image files + self.assertRaises(errors.ReaderError, rdr, 'invalid.jpg') + # returns dict with exif info + self.assertDictEqual(rdr(os.path.join(os.path.dirname(__file__), 'testimage_exif.jpg')), { + 'Exif.Image.Artist': 'nobody', + 'Exif.Image.ExifTag': '110', + 'Exif.Image.ResolutionUnit': '2', + 'Exif.Image.XResolution': '300/1', + 'Exif.Image.YCbCrPositioning': '1', + 'Exif.Image.YResolution': '300/1', + 'Exif.Photo.ColorSpace': '65535', + 'Exif.Photo.ComponentsConfiguration': '1 2 3 0', + 'Exif.Photo.ExifVersion': '48 50 51 50', + 'Exif.Photo.FlashpixVersion': '48 49 48 48', + 'Exif.Photo.ISOSpeedRatings': '200', + }) + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/reader/testimage_exif.jpg b/test/reader/testimage_exif.jpg new file mode 100644 index 0000000..a774bc2 Binary files /dev/null and b/test/reader/testimage_exif.jpg differ -- cgit v1.2.3 From 4b5c4d486bb4f0f4da2e25ad464e8336a781cdcb Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Wed, 1 Mar 2023 22:31:03 +0100 Subject: removed module header stubs --- test/reader/image/load_nef.py | 5 ----- test/reader/image/test_image.py | 5 ----- test/reader/image/test_pillow.py | 5 ----- test/reader/image/test_raw_image.py | 5 ----- test/reader/preview/load_nef.py | 5 ----- test/reader/preview/test_pg.py | 5 ----- test/reader/preview/test_pillow.py | 5 ----- test/reader/preview/test_preview.py | 5 ----- test/reader/preview/test_rawpy.py | 5 ----- test/reader/preview/test_utils.py | 5 ----- test/reader/test_base.py | 5 ----- test/reader/test_builder.py | 5 ----- test/reader/test_chain.py | 5 ----- test/reader/test_exif.py | 5 ----- test/reader/test_path.py | 5 ----- test/reader/test_stat.py | 5 ----- 16 files changed, 80 deletions(-) (limited to 'test/reader') diff --git a/test/reader/image/load_nef.py b/test/reader/image/load_nef.py index 5ba0adc..02be470 100644 --- a/test/reader/image/load_nef.py +++ b/test/reader/image/load_nef.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import os diff --git a/test/reader/image/test_image.py b/test/reader/image/test_image.py index 26f6a93..ee9b8f9 100644 --- a/test/reader/image/test_image.py +++ b/test/reader/image/test_image.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import importlib import os diff --git a/test/reader/image/test_pillow.py b/test/reader/image/test_pillow.py index 8abf5c1..2cff768 100644 --- a/test/reader/image/test_pillow.py +++ b/test/reader/image/test_pillow.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import os import unittest diff --git a/test/reader/image/test_raw_image.py b/test/reader/image/test_raw_image.py index ba21b5a..0a5ed63 100644 --- a/test/reader/image/test_raw_image.py +++ b/test/reader/image/test_raw_image.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import importlib import os diff --git a/test/reader/preview/load_nef.py b/test/reader/preview/load_nef.py index 5ba0adc..02be470 100644 --- a/test/reader/preview/load_nef.py +++ b/test/reader/preview/load_nef.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import os diff --git a/test/reader/preview/test_pg.py b/test/reader/preview/test_pg.py index e492cfa..381344f 100644 --- a/test/reader/preview/test_pg.py +++ b/test/reader/preview/test_pg.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports from functools import partial import os diff --git a/test/reader/preview/test_pillow.py b/test/reader/preview/test_pillow.py index ca38d89..d213bbb 100644 --- a/test/reader/preview/test_pillow.py +++ b/test/reader/preview/test_pillow.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports from functools import partial import os diff --git a/test/reader/preview/test_preview.py b/test/reader/preview/test_preview.py index fde610f..e144877 100644 --- a/test/reader/preview/test_preview.py +++ b/test/reader/preview/test_preview.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports from functools import partial import importlib diff --git a/test/reader/preview/test_rawpy.py b/test/reader/preview/test_rawpy.py index ed35f53..11a6f9b 100644 --- a/test/reader/preview/test_rawpy.py +++ b/test/reader/preview/test_rawpy.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports from functools import partial import importlib diff --git a/test/reader/preview/test_utils.py b/test/reader/preview/test_utils.py index c10c38c..2b15bc6 100644 --- a/test/reader/preview/test_utils.py +++ b/test/reader/preview/test_utils.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import os import unittest diff --git a/test/reader/test_base.py b/test/reader/test_base.py index 41f4c29..5dd2855 100644 --- a/test/reader/test_base.py +++ b/test/reader/test_base.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import unittest diff --git a/test/reader/test_builder.py b/test/reader/test_builder.py index 92e9edc..84e8e7a 100644 --- a/test/reader/test_builder.py +++ b/test/reader/test_builder.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import unittest diff --git a/test/reader/test_chain.py b/test/reader/test_chain.py index 901faa1..665aabc 100644 --- a/test/reader/test_chain.py +++ b/test/reader/test_chain.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import logging import os diff --git a/test/reader/test_exif.py b/test/reader/test_exif.py index f1330da..b2bf843 100644 --- a/test/reader/test_exif.py +++ b/test/reader/test_exif.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import os import unittest diff --git a/test/reader/test_path.py b/test/reader/test_path.py index 95e447f..f2eee06 100644 --- a/test/reader/test_path.py +++ b/test/reader/test_path.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import unittest diff --git a/test/reader/test_stat.py b/test/reader/test_stat.py index fd9fdcd..f36b8b3 100644 --- a/test/reader/test_stat.py +++ b/test/reader/test_stat.py @@ -1,9 +1,4 @@ -""" -Part of the bsie test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # standard imports import os import unittest -- cgit v1.2.3 From 70d77819a84c73292825b81f952e162bb30753d7 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 2 Mar 2023 08:56:57 +0100 Subject: reader error: untangle generic from unsupported format errors --- test/reader/image/test_raw_image.py | 4 ++-- test/reader/preview/test_pillow.py | 6 +++++- test/reader/test_exif.py | 13 +++++++++++-- test/reader/testimage_exif_corrupted.jpg | Bin 0 -> 551 bytes 4 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 test/reader/testimage_exif_corrupted.jpg (limited to 'test/reader') diff --git a/test/reader/image/test_raw_image.py b/test/reader/image/test_raw_image.py index 0a5ed63..3b240d0 100644 --- a/test/reader/image/test_raw_image.py +++ b/test/reader/image/test_raw_image.py @@ -32,10 +32,10 @@ class TestRawImage(unittest.TestCase): #self.assertEqual(img.getdata().getpixel((0, 0)), (0, 0, 0)) img.close() # raises exception when image cannot be read + self.assertRaises(errors.UnsupportedFileFormatError, rdr, + os.path.join(os.path.dirname(__file__), 'testimage.jpg')) self.assertRaises(errors.ReaderError, rdr, os.path.join(os.path.dirname(__file__), 'invalid.nef')) - self.assertRaises(errors.ReaderError, rdr, - os.path.join(os.path.dirname(__file__), 'testimage.jpg')) diff --git a/test/reader/preview/test_pillow.py b/test/reader/preview/test_pillow.py index d213bbb..20f08ec 100644 --- a/test/reader/preview/test_pillow.py +++ b/test/reader/preview/test_pillow.py @@ -20,11 +20,15 @@ class TestPillowPreviewReader(unittest.TestCase): def test_call(self): rdr = PillowPreviewReader() # raises exception when image cannot be read - self.assertRaises(errors.ReaderError, rdr, + self.assertRaises(errors.UnsupportedFileFormatError, rdr, os.path.join(os.path.dirname(__file__), 'invalid.jpg')) + # raises exception when image cannot be read + self.assertRaises(errors.ReaderError, rdr, + os.path.join(os.path.dirname(__file__), 'inexistent.jpg')) # raises exception when image has invalid type self.assertRaises(errors.UnsupportedFileFormatError, rdr, os.path.join(os.path.dirname(__file__), 'invalid.foo')) + # proper file produces a generator gen = rdr(os.path.join(os.path.dirname(__file__), 'testimage.jpg')) self.assertIsInstance(gen, partial) diff --git a/test/reader/test_exif.py b/test/reader/test_exif.py index b2bf843..de6e801 100644 --- a/test/reader/test_exif.py +++ b/test/reader/test_exif.py @@ -3,6 +3,9 @@ import os import unittest +# external imports +import pyexiv2 + # bsie imports from bsie.utils import errors @@ -16,9 +19,15 @@ class TestExif(unittest.TestCase): def test_call(self): rdr = Exif() # discards non-image files - self.assertRaises(errors.UnsupportedFileFormatError, rdr, 'invalid.doc') + self.assertRaises(errors.UnsupportedFileFormatError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.doc')) + # raises on invalid image files + self.assertRaises(errors.UnsupportedFileFormatError, rdr, + os.path.join(os.path.dirname(__file__), 'invalid.jpg')) # raises on invalid image files - self.assertRaises(errors.ReaderError, rdr, 'invalid.jpg') + pyexiv2.set_log_level(3) # suppress log message + self.assertRaises(errors.ReaderError, rdr, + os.path.join(os.path.dirname(__file__), 'testimage_exif_corrupted.jpg')) # returns dict with exif info self.assertDictEqual(rdr(os.path.join(os.path.dirname(__file__), 'testimage_exif.jpg')), { 'Exif.Image.Artist': 'nobody', diff --git a/test/reader/testimage_exif_corrupted.jpg b/test/reader/testimage_exif_corrupted.jpg new file mode 100644 index 0000000..e51a9dc Binary files /dev/null and b/test/reader/testimage_exif_corrupted.jpg differ -- cgit v1.2.3 From ba6329bbe14c832d42773dee2fe30bd7669ca255 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 2 Mar 2023 08:58:29 +0100 Subject: various minor fixes --- test/reader/preview/test_pg.py | 1 + 1 file changed, 1 insertion(+) (limited to 'test/reader') diff --git a/test/reader/preview/test_pg.py b/test/reader/preview/test_pg.py index 381344f..30095c5 100644 --- a/test/reader/preview/test_pg.py +++ b/test/reader/preview/test_pg.py @@ -52,6 +52,7 @@ class TestPreviewGeneratorReader(unittest.TestCase): self.assertEqual(sum(img.getdata()), 20258) # cleanup img.close() + del rdr # can define a cache dir pg_dir = tempfile.mkdtemp(prefix='bsie-test') -- cgit v1.2.3