Skip to content
Snippets Groups Projects
exiftool.py 1.74 KiB
Newer Older
  • Learn to ignore specific revisions
  • import json
    import os
    import re
    import shutil
    import subprocess
    import tempfile
    
    
    from typing import Dict, Union, Set, Callable, Any
    
    
    from . import abstract
    
    # Make pyflakes happy
    assert Set
    
    
    class ExiftoolParser(abstract.AbstractParser):
        """ Exiftool is often the easiest way to get all the metadata
        from a import file, hence why several parsers are re-using its `get_meta`
        method.
        """
        meta_whitelist = set()  # type: Set[str]
    
    
        def _handle_problematic_filename(self, callback: Callable[[str], Any]) -> bytes:
            """ This method takes a filename with a potentially problematic name,
            and safely applies a `callback` to it.
            """
            if re.search('^[a-z0-9/]', self.filename) is not None:
                return callback(self.filename)
    
    
            tmpdirname = tempfile.mkdtemp()
            fname = os.path.join(tmpdirname, "temp_file")
    
            shutil.copy(self.filename, fname)
    
            out = callback(fname)
            shutil.rmtree(tmpdirname)
            return out
    
        def get_meta(self) -> Dict[str, Union[str, dict]]:
            fun = lambda f: subprocess.check_output([_get_exiftool_path(), '-json', f])
    
            out = self._handle_problematic_filename(fun)
    
            meta = json.loads(out.decode('utf-8'))[0]
            for key in self.meta_whitelist:
                meta.pop(key, None)
            return meta
    
    def _get_exiftool_path() -> str:  # pragma: no cover
        exiftool_path = '/usr/bin/exiftool'
        if os.path.isfile(exiftool_path):
            if os.access(exiftool_path, os.X_OK):
                return exiftool_path
    
        # ArchLinux
        exiftool_path = '/usr/bin/vendor_perl/exiftool'
        if os.path.isfile(exiftool_path):
            if os.access(exiftool_path, os.X_OK):
                return exiftool_path
    
        raise RuntimeError("Unable to find exiftool")