Skip to content

Commit

Permalink
Improve errors when libmediainfo can't be loaded
Browse files Browse the repository at this point in the history
  • Loading branch information
sbraz committed Apr 30, 2021
1 parent abf927e commit b5c5fed
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 21 deletions.
51 changes: 30 additions & 21 deletions pymediainfo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,26 @@ def _define_library_prototypes(cls, lib: Any) -> Any:
lib.MediaInfo_Close.argtypes = [ctypes.c_void_p]
lib.MediaInfo_Close.restype = None

@staticmethod
def _get_library_paths(os_is_nt: bool) -> Tuple[str]:
if os_is_nt:
library_paths = ("MediaInfo.dll",)
elif sys.platform == "darwin":
library_paths = ("libmediainfo.0.dylib", "libmediainfo.dylib")
else:
library_paths = ("libmediainfo.so.0",)
script_dir = os.path.dirname(__file__)
# Look for the library file in the script folder
for library in library_paths:
absolute_library_path = os.path.join(script_dir, library)
if os.path.isfile(absolute_library_path):
# If we find it, don't try any other filename
library_paths = (absolute_library_path,)
break
return library_paths

@classmethod
def _get_library(
# pylint: disable=too-many-branches
cls,
library_file: Optional[str] = None,
) -> Tuple[Any, Any, str, Tuple[int, ...]]:
Expand All @@ -288,25 +305,13 @@ def _get_library(
else:
lib_type = ctypes.CDLL
if library_file is None:
if os_is_nt:
library_names = ("MediaInfo.dll",)
elif sys.platform == "darwin":
library_names = ("libmediainfo.0.dylib", "libmediainfo.dylib")
else:
library_names = ("libmediainfo.so.0",)
script_dir = os.path.dirname(__file__)
# Look for the library file in the script folder
for library in library_names:
lib_path = os.path.join(script_dir, library)
if os.path.isfile(lib_path):
# If we find it, don't try any other filename
library_names = (lib_path,)
break
library_paths = cls._get_library_paths(os_is_nt)
else:
library_names = (library_file,)
for library in library_names:
library_paths = (library_file,)
exceptions = []
for library_path in library_paths:
try:
lib = lib_type(library)
lib = lib_type(library_path)
cls._define_library_prototypes(lib)
# Without a handle, there might be problems when using concurrent threads
# https://github.com/sbraz/pymediainfo/issues/76#issuecomment-574759621
Expand All @@ -319,9 +324,13 @@ def _get_library(
else:
raise RuntimeError("Could not determine library version")
return (lib, handle, lib_version_str, lib_version)
except OSError:
pass
raise OSError("Failed to load library")
except OSError as exc:
exceptions.append(str(exc))
raise OSError(
"Failed to load library from {} - {}".format(
", ".join(library_paths), ", ".join(exceptions)
)
)

@classmethod
def can_parse(cls, library_file: Optional[str] = None) -> bool:
Expand Down
10 changes: 10 additions & 0 deletions tests/test_pymediainfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import os
import pathlib
import pickle
import tempfile
import threading
import unittest
import xml
Expand Down Expand Up @@ -113,6 +114,15 @@ def test_full_option(self):
self.assertEqual(self.media_info.tracks[0].footersize, "59")
self.assertEqual(self.non_full_mi.tracks[0].footersize, None)

def test_raises_on_nonexistent_library(self): # pylint: disable=no-self-use
with tempfile.TemporaryDirectory() as tmp_dir:
nonexistent_library = os.path.join(tmp_dir, "nonexistent-libmediainfo.so")
with pytest.raises(OSError) as exc:
MediaInfo.parse(
os.path.join(data_dir, "sample.mp4"), library_file=nonexistent_library
)
assert rf"Failed to load library from {nonexistent_library}" in str(exc.value)


class MediaInfoFileLikeTest(unittest.TestCase):
def test_can_parse(self): # pylint: disable=no-self-use
Expand Down

0 comments on commit b5c5fed

Please sign in to comment.