diff --git a/Makefile b/Makefile index 1920450..8e8a097 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -all: lint unit +all: lint test export PYTHONPATH:=${PWD} version=`python -c 'import filetype; print(filetype.version)'` @@ -9,7 +9,10 @@ lint: test: clean lint @echo "Running tests ..." - @python -m unittest discover + @python -m pytest -v tests + +coverage: + @python -m pytest --cov-branch --cov-report html --cov=filetype tests/ documentation: @pdoc --html --overwrite --all-submodules --html-dir docs filetype diff --git a/filetype/helpers.py b/filetype/helpers.py index 03de232..91e9040 100644 --- a/filetype/helpers.py +++ b/filetype/helpers.py @@ -21,7 +21,7 @@ def is_extension_supported(ext): Otherwise False. """ for kind in TYPES: - if kind.extension is ext: + if kind.extension == ext: return True return False @@ -39,7 +39,7 @@ def is_mime_supported(mime): Otherwise False. """ for kind in TYPES: - if kind.mime is mime: + if kind.mime == mime: return True return False diff --git a/requirements-dev.txt b/requirements-dev.txt index cb64874..ba1cf94 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,4 @@ -pytest flake8 +pytest +pytest-benchmark +pytest-cov diff --git a/tests/__init__.py b/tests/__init__.py index 40a96af..a7af50f 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1 +1,6 @@ # -*- coding: utf-8 -*- + +import os + +# Absolute path to fixtures directory +FIXTURES = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'fixtures') diff --git a/tests/fixtures/sample.mp3 b/tests/fixtures/sample.mp3 new file mode 100644 index 0000000..11e4534 Binary files /dev/null and b/tests/fixtures/sample.mp3 differ diff --git a/tests/fixtures/sample.tar b/tests/fixtures/sample.tar new file mode 100644 index 0000000..f9c2e44 Binary files /dev/null and b/tests/fixtures/sample.tar differ diff --git a/tests/fixtures/sample.ttf b/tests/fixtures/sample.ttf new file mode 100644 index 0000000..889c594 Binary files /dev/null and b/tests/fixtures/sample.ttf differ diff --git a/tests/fixtures/sample.zip b/tests/fixtures/sample.zip new file mode 100644 index 0000000..c547942 Binary files /dev/null and b/tests/fixtures/sample.zip differ diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py index 0992ed3..3d6bd85 100644 --- a/tests/test_benchmark.py +++ b/tests/test_benchmark.py @@ -3,39 +3,30 @@ from __future__ import absolute_import import os - import filetype -# Absolute path to fixtures directory -FIXTURES = os.path.dirname(os.path.abspath(__file__)) + '/fixtures' - - -def test_infer_image_from_disk(benchmark): - benchmark(filetype.guess, FIXTURES + '/sample.jpg') - - -def test_infer_video_from_disk(benchmark): - benchmark(filetype.guess, FIXTURES + '/sample.mp4') - - -def test_infer_zip_from_disk(benchmark): - benchmark(filetype.guess, FIXTURES + '/sample.zip') - - -def test_infer_tar_from_disk(benchmark): - benchmark(filetype.guess, FIXTURES + '/sample.tar') - +import pytest -def test_infer_image_from_bytes(benchmark): - benchmark(filetype.guess, - bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08])) +from . import FIXTURES -def test_infer_video_from_bytes(benchmark): - benchmark(filetype.guess, - bytearray([0x1A, 0x45, 0xDF, 0xA3, 0x08])) +@pytest.mark.parametrize('filename', + [ + 'sample.jpg', + 'sample.mp4', + 'sample.zip', + 'sample.tar', + ]) +def test_infer_from_disk(benchmark, filename): + benchmark(filetype.guess, os.path.join(FIXTURES, filename)) -def test_infer_audio_from_bytes(benchmark): - benchmark(filetype.guess, - bytearray([0x4D, 0x54, 0x68, 0xA3, 0x64])) +@pytest.mark.parametrize('bytes_', + [ + [0xFF, 0xD8, 0xFF, 0x00, 0x08], + [0x1A, 0x45, 0xDF, 0xA3, 0x08], + [0x4D, 0x54, 0x68, 0xA3, 0x64], + ], + ids=['image', 'video', 'audio']) +def test_infer_from_bytes(benchmark, bytes_): + benchmark(filetype.guess, bytearray(bytes_)) diff --git a/tests/test_filetype.py b/tests/test_filetype.py index 3fb9a5f..61a0bfb 100644 --- a/tests/test_filetype.py +++ b/tests/test_filetype.py @@ -3,84 +3,166 @@ from __future__ import absolute_import import os -import unittest +import sys + +# Python 2.7 workaround +try: + import pathlib +except ImportError: + pathlib = None import filetype +from filetype.types import image +from filetype.types.base import Type + +import pytest -# Absolute path to fixtures directory -FIXTURES = os.path.dirname(os.path.abspath(__file__)) + '/fixtures' +from . import FIXTURES -class TestFileType(unittest.TestCase): +class TestFileType(object): + def test_guess_file_path(self): - kind = filetype.guess(FIXTURES + '/sample.jpg') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/jpeg') - self.assertEqual(kind.extension, 'jpg') + kind = filetype.guess(os.path.join(FIXTURES, 'sample.jpg')) + assert kind is not None + assert kind.mime == 'image/jpeg' + assert kind.extension == 'jpg' def test_guess_buffer(self): buf = bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08]) kind = filetype.guess(buf) - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/jpeg') - self.assertEqual(kind.extension, 'jpg') + assert kind is not None + assert kind.mime == 'image/jpeg' + assert kind.extension == 'jpg' def test_guess_buffer_invalid(self): buf = bytearray([0xFF, 0x00, 0x00, 0x00, 0x00]) kind = filetype.guess(buf) - self.assertTrue(kind is None) + assert kind is None def test_guess_memoryview(self): buf = memoryview(bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08])) kind = filetype.guess(buf) - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/jpeg') - self.assertEqual(kind.extension, 'jpg') + assert kind is not None + assert kind.mime == 'image/jpeg' + assert kind.extension == 'jpg' + + @pytest.mark.skipif(sys.version_info < (3,), + reason="No workarounds anymore for python 2.7") + def test_guess_bytes(self): + buf = bytes(bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08])) + kind = filetype.guess(buf) + assert kind is not None + assert kind.mime == 'image/jpeg' + assert kind.extension == 'jpg' + + @pytest.mark.skipif(sys.version_info < (3, 6), + reason="No workarounds for unsupported versions") + def test_guess_pathlib(self): + path = pathlib.Path(os.path.join(FIXTURES, 'sample.jpg')) + kind = filetype.guess(path) + assert kind is not None + assert kind.mime == 'image/jpeg' + assert kind.extension == 'jpg' + + @pytest.mark.skipif(sys.version_info < (3, 6), + reason="No workarounds for unsupported versions") + def test_invalid_input(self): + with pytest.raises(TypeError): + filetype.guess(tuple) + +class TestFileTypeExtension(object): -class TestFileTypeExtension(unittest.TestCase): def test_guess_extension_file_path(self): - ext = filetype.guess_extension(FIXTURES + '/sample.jpg') - self.assertTrue(ext is not None) - self.assertEqual(ext, 'jpg') + ext = filetype.guess_extension(os.path.join(FIXTURES, 'sample.jpg')) + assert ext is not None + assert ext == 'jpg' def test_guess_extension_buffer(self): buf = bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08]) ext = filetype.guess_extension(buf) - self.assertTrue(ext is not None) - self.assertEqual(ext, 'jpg') + assert ext is not None + assert ext == 'jpg' def test_guess_extension_buffer_invalid(self): buf = bytearray([0xFF, 0x00, 0x00, 0x00, 0x00]) ext = filetype.guess_extension(buf) - self.assertTrue(ext is None) + assert ext is None def test_guess_extension_memoryview(self): buf = memoryview(bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08])) ext = filetype.guess_extension(buf) - self.assertTrue(ext is not None) - self.assertEqual(ext, 'jpg') + assert ext is not None + assert ext == 'jpg' -class TestFileTypeMIME(unittest.TestCase): +class TestFileTypeMIME(object): + def test_guess_mime_file_path(self): - mime = filetype.guess_mime(FIXTURES + '/sample.jpg') - self.assertTrue(mime is not None) - self.assertEqual(mime, 'image/jpeg') + mime = filetype.guess_mime(os.path.join(FIXTURES, 'sample.jpg')) + assert mime is not None + assert mime == 'image/jpeg' def test_guess_mime_buffer(self): buf = bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08]) mime = filetype.guess_mime(buf) - self.assertTrue(mime is not None) - self.assertEqual(mime, 'image/jpeg') + assert mime is not None + assert mime == 'image/jpeg' def test_guess_mime_buffer_invalid(self): buf = bytearray([0xFF, 0x00, 0x00, 0x00, 0x00]) mime = filetype.guess_mime(buf) - self.assertTrue(mime is None) + assert mime is None def test_guess_mime_memoryview(self): buf = memoryview(bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08])) mime = filetype.guess_mime(buf) - self.assertTrue(mime is not None) - self.assertEqual(mime, 'image/jpeg') + assert mime is not None + assert mime == 'image/jpeg' + + +def test_get_type_mime(): + type_ = filetype.get_type(mime='image/png') + assert isinstance(type_, image.Png) + + +def test_get_type_ext(): + type_ = filetype.get_type(ext='png') + assert isinstance(type_, image.Png) + + +def test_get_type(): + type_ = filetype.get_type(mime='image/png', ext='png') + assert isinstance(type_, image.Png) + + +def test_get_type_invalid(): + type_ = filetype.get_type(mime='foo', ext='bar') + assert type_ is None + + +def test_invalid_custom_type(): + with pytest.raises(TypeError): + filetype.add_type(tuple) + + +@pytest.mark.skipif(sys.version_info < (3,), + reason="No workarounds anymore for python 2.7") +def test_custom_type(): + mime = 'app/bar' + ext = 'bar' + + class Custom(Type): + + def __init__(self): + super().__init__(mime=mime, extension=ext) + + def match(self, buf): + return buf == b"bar" + + filetype.add_type(Custom()) + kind = filetype.guess(b"bar") + + assert kind.extension == ext + assert kind.mime == mime diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 40a96af..851a7fd 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -1 +1,45 @@ # -*- coding: utf-8 -*- + +from __future__ import absolute_import + +import os + +from filetype import helpers + +from . import FIXTURES + + +def test_supported_extension(): + assert helpers.is_extension_supported('jpg') is True + + +def test_unsupported_extension(): + assert helpers.is_extension_supported('foo') is False + + +def test_supported_mime(): + assert helpers.is_mime_supported('image/jpeg') is True + + +def test_unsupported_mime(): + assert helpers.is_mime_supported('foo') is False + + +def test_is_archive(): + assert helpers.is_archive(os.path.join(FIXTURES, 'sample.tar')) is True + + +def test_is_font(): + assert helpers.is_font(os.path.join(FIXTURES, 'sample.ttf')) is True + + +def test_is_image(): + assert helpers.is_image(os.path.join(FIXTURES, 'sample.png')) is True + + +def test_is_video(): + assert helpers.is_video(os.path.join(FIXTURES, 'sample.mp4')) is True + + +def test_is_audio(): + assert helpers.is_audio(os.path.join(FIXTURES, 'sample.mp3')) is True diff --git a/tests/test_types.py b/tests/test_types.py index 8bbb5f2..58fbee1 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -3,59 +3,28 @@ from __future__ import absolute_import import os -import unittest import filetype -# Absolute path to fixtures directory -FIXTURES = os.path.dirname(os.path.abspath(__file__)) + '/fixtures' - - -class TestFileType(unittest.TestCase): - def test_guess_jpeg(self): - kind = filetype.guess(FIXTURES + '/sample.jpg') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/jpeg') - self.assertEqual(kind.extension, 'jpg') - - def test_guess_jpx(self): - kind = filetype.guess(FIXTURES + '/sample.jpx') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/jpx') - self.assertEqual(kind.extension, 'jpx') - - def test_guess_gif(self): - kind = filetype.guess(FIXTURES + '/sample.gif') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/gif') - self.assertEqual(kind.extension, 'gif') - - def test_guess_heic(self): - kind = filetype.guess(FIXTURES + '/sample.heic') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/heic') - self.assertEqual(kind.extension, 'heic') - - def test_guess_mp4(self): - kind = filetype.guess(FIXTURES + '/sample.mp4') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'video/mp4') - self.assertEqual(kind.extension, 'mp4') - - def test_guess_png(self): - kind = filetype.guess(FIXTURES + '/sample.png') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/png') - self.assertEqual(kind.extension, 'png') - - def test_guess_tif(self): - kind = filetype.guess(FIXTURES + '/sample.tif') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'image/tiff') - self.assertEqual(kind.extension, 'tif') - - def test_guess_mov(self): - kind = filetype.guess(FIXTURES + '/sample.mov') - self.assertTrue(kind is not None) - self.assertEqual(kind.mime, 'video/quicktime') - self.assertEqual(kind.extension, 'mov') +import pytest + +from . import FIXTURES + + +@pytest.mark.parametrize("mime,ext,filename", + [ + ('image/jpeg', 'jpg', 'sample.jpg'), + ('image/png', 'png', 'sample.png'), + ('image/jpx', 'jpx', 'sample.jpx'), + ('image/gif', 'gif', 'sample.gif'), + ('image/heic', 'heic', 'sample.heic'), + ('image/tiff', 'tif', 'sample.tif'), + ('video/mp4', 'mp4', 'sample.mp4'), + ('video/quicktime', 'mov', 'sample.mov'), + ]) +def test_guess_filetype(mime, ext, filename): + kind = filetype.guess(os.path.join(FIXTURES, filename)) + + assert kind is not None + assert kind.mime == mime + assert kind.extension == ext diff --git a/tox.ini b/tox.ini index 4ff7e60..1d2daf3 100644 --- a/tox.ini +++ b/tox.ini @@ -4,11 +4,12 @@ # and then run "tox" from this directory. [tox] -envlist = py{27,35,36,37,38,39}, lint, doc, clean +envlist = py{27,35,36,37,38,39}, lint skip_missing_interpreters = true [testenv] -commands = python -m unittest discover +deps = -r requirements-dev.txt +commands = pytest -v tests [testenv:lint] basepython = python3 @@ -16,6 +17,10 @@ deps = flake8 commands = flake8 {toxinidir} +[testenv:coverage] +basepython = python3 +commands = pytest --cov-branch --cov-report html --cov=filetype tests/ + [testenv:doc] basepython = python3 deps =