From 2ba38dd2a18ab57ed7aac7ccdd6a42ff5e4d4eb7 Mon Sep 17 00:00:00 2001 From: jvoisin Date: Fri, 12 Oct 2018 11:58:01 +0200 Subject: Bump mypy typing coverage --- libmat2/__init__.py | 5 +++-- libmat2/abstract.py | 4 ++-- libmat2/archive.py | 3 ++- libmat2/audio.py | 28 +++++++++++++++++----------- libmat2/harmless.py | 4 ++-- libmat2/images.py | 20 ++++++++++---------- libmat2/office.py | 6 +++--- libmat2/pdf.py | 3 ++- libmat2/torrent.py | 2 +- 9 files changed, 42 insertions(+), 33 deletions(-) (limited to 'libmat2') diff --git a/libmat2/__init__.py b/libmat2/__init__.py index fbb61bc..f55a14c 100644 --- a/libmat2/__init__.py +++ b/libmat2/__init__.py @@ -8,6 +8,7 @@ from typing import Dict, Optional # make pyflakes happy assert Dict +assert Optional # A set of extension that aren't supported, despite matching a supported mimetype UNSUPPORTED_EXTENSIONS = { @@ -36,7 +37,7 @@ DEPENDENCIES = { 'mutagen': 'Mutagen', } -def _get_exiftool_path() -> Optional[str]: # pragma: no cover +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): @@ -48,7 +49,7 @@ def _get_exiftool_path() -> Optional[str]: # pragma: no cover if os.access(exiftool_path, os.X_OK): return exiftool_path - return None + raise ValueError def check_dependencies() -> dict: ret = collections.defaultdict(bool) # type: Dict[str, bool] diff --git a/libmat2/abstract.py b/libmat2/abstract.py index 5bcaa69..0084796 100644 --- a/libmat2/abstract.py +++ b/libmat2/abstract.py @@ -1,6 +1,6 @@ import abc import os -from typing import Set, Dict +from typing import Set, Dict, Union assert Set # make pyflakes happy @@ -22,7 +22,7 @@ class AbstractParser(abc.ABC): self.lightweight_cleaning = False @abc.abstractmethod - def get_meta(self) -> Dict[str, str]: + def get_meta(self) -> Dict[str, Union[str, dict]]: pass # pragma: no cover @abc.abstractmethod diff --git a/libmat2/archive.py b/libmat2/archive.py index 016142d..f788ecc 100644 --- a/libmat2/archive.py +++ b/libmat2/archive.py @@ -4,13 +4,14 @@ import tempfile import os import logging import shutil -from typing import Dict, Set, Pattern +from typing import Dict, Set, Pattern, Union from . import abstract, UnknownMemberPolicy, parser_factory # Make pyflakes happy assert Set assert Pattern +assert Union class ArchiveBasedAbstractParser(abstract.AbstractParser): diff --git a/libmat2/audio.py b/libmat2/audio.py index b67f766..bfe7f79 100644 --- a/libmat2/audio.py +++ b/libmat2/audio.py @@ -2,6 +2,7 @@ import mimetypes import os import shutil import tempfile +from typing import Dict, Union import mutagen @@ -16,13 +17,13 @@ class MutagenParser(abstract.AbstractParser): except mutagen.MutagenError: raise ValueError - def get_meta(self): + def get_meta(self) -> Dict[str, Union[str, dict]]: f = mutagen.File(self.filename) if f.tags: return {k:', '.join(v) for k, v in f.tags.items()} return {} - def remove_all(self): + def remove_all(self) -> bool: shutil.copy(self.filename, self.output_filename) f = mutagen.File(self.output_filename) f.delete() @@ -33,8 +34,8 @@ class MutagenParser(abstract.AbstractParser): class MP3Parser(MutagenParser): mimetypes = {'audio/mpeg', } - def get_meta(self): - metadata = {} + def get_meta(self) -> Dict[str, Union[str, dict]]: + metadata = {} # type: Dict[str, Union[str, dict]] meta = mutagen.File(self.filename).tags for key in meta: metadata[key.rstrip(' \t\r\n\0')] = ', '.join(map(str, meta[key].text)) @@ -48,7 +49,7 @@ class OGGParser(MutagenParser): class FLACParser(MutagenParser): mimetypes = {'audio/flac', 'audio/x-flac'} - def remove_all(self): + def remove_all(self) -> bool: shutil.copy(self.filename, self.output_filename) f = mutagen.File(self.output_filename) f.clear_pictures() @@ -56,16 +57,21 @@ class FLACParser(MutagenParser): f.save(deleteid3=True) return True - def get_meta(self): + def get_meta(self) -> Dict[str, Union[str, dict]]: meta = super().get_meta() for num, picture in enumerate(mutagen.File(self.filename).pictures): name = picture.desc if picture.desc else 'Cover %d' % num + extension = mimetypes.guess_extension(picture.mime) + if extension is None: # pragma: no cover + meta[name] = 'harmful data' + continue + _, fname = tempfile.mkstemp() + fname = fname + extension with open(fname, 'wb') as f: f.write(picture.data) - extension = mimetypes.guess_extension(picture.mime) - shutil.move(fname, fname + extension) - p, _ = parser_factory.get_parser(fname+extension) - meta[name] = p.get_meta() if p else 'harmful data' - os.remove(fname + extension) + p, _ = parser_factory.get_parser(fname) # type: ignore + # Mypy chokes on ternaries :/ + meta[name] = p.get_meta() if p else 'harmful data' # type: ignore + os.remove(fname) return meta diff --git a/libmat2/harmless.py b/libmat2/harmless.py index f646099..fad0ef8 100644 --- a/libmat2/harmless.py +++ b/libmat2/harmless.py @@ -1,5 +1,5 @@ import shutil -from typing import Dict +from typing import Dict, Union from . import abstract @@ -7,7 +7,7 @@ class HarmlessParser(abstract.AbstractParser): """ This is the parser for filetypes that can not contain metadata. """ mimetypes = {'text/plain', 'image/x-ms-bmp'} - def get_meta(self) -> Dict[str, str]: + def get_meta(self) -> Dict[str, Union[str, dict]]: return dict() def remove_all(self) -> bool: diff --git a/libmat2/images.py b/libmat2/images.py index 8f7a98d..a29cbb7 100644 --- a/libmat2/images.py +++ b/libmat2/images.py @@ -5,7 +5,7 @@ import os import shutil import tempfile import re -from typing import Set +from typing import Set, Dict, Union import cairo @@ -25,7 +25,7 @@ class _ImageParser(abstract.AbstractParser): meta_whitelist = set() # type: Set[str] @staticmethod - def __handle_problematic_filename(filename: str, callback) -> str: + def __handle_problematic_filename(filename: str, callback) -> bytes: """ This method takes a filename with a problematic name, and safely applies it a `callback`.""" tmpdirname = tempfile.mkdtemp() @@ -35,7 +35,7 @@ class _ImageParser(abstract.AbstractParser): shutil.rmtree(tmpdirname) return out - def get_meta(self): + def get_meta(self) -> Dict[str, Union[str, dict]]: """ There is no way to escape the leading(s) dash(es) of the current self.filename to prevent parameter injections, so we need to take care of this. @@ -71,7 +71,7 @@ class PNGParser(_ImageParser): except MemoryError: # pragma: no cover raise ValueError - def remove_all(self): + def remove_all(self) -> bool: surface = cairo.ImageSurface.create_from_png(self.filename) surface.write_to_png(self.output_filename) return True @@ -83,7 +83,12 @@ class GdkPixbufAbstractParser(_ImageParser): """ _type = '' - def remove_all(self): + def __init__(self, filename): + super().__init__(filename) + if imghdr.what(filename) != self._type: # better safe than sorry + raise ValueError + + def remove_all(self) -> bool: _, extension = os.path.splitext(self.filename) pixbuf = GdkPixbuf.Pixbuf.new_from_file(self.filename) if extension.lower() == '.jpg': @@ -91,11 +96,6 @@ class GdkPixbufAbstractParser(_ImageParser): pixbuf.savev(self.output_filename, extension[1:], [], []) return True - def __init__(self, filename): - super().__init__(filename) - if imghdr.what(filename) != self._type: # better safe than sorry - raise ValueError - class JPGParser(GdkPixbufAbstractParser): _type = 'jpeg' diff --git a/libmat2/office.py b/libmat2/office.py index 32e7b75..c10664f 100644 --- a/libmat2/office.py +++ b/libmat2/office.py @@ -2,7 +2,7 @@ import logging import os import re import zipfile -from typing import Dict, Set, Pattern, Tuple +from typing import Dict, Set, Pattern, Tuple, Union import xml.etree.ElementTree as ET # type: ignore @@ -296,7 +296,7 @@ class MSOfficeParser(ArchiveBasedAbstractParser): return True - def get_meta(self) -> Dict[str, str]: + def get_meta(self) -> Dict[str, Union[str, dict]]: """ Yes, I know that parsing xml with regexp ain't pretty, be my guest and fix it if you want. @@ -381,7 +381,7 @@ class LibreOfficeParser(ArchiveBasedAbstractParser): return False return True - def get_meta(self) -> Dict[str, str]: + def get_meta(self) -> Dict[str, Union[str, dict]]: """ Yes, I know that parsing xml with regexp ain't pretty, be my guest and fix it if you want. diff --git a/libmat2/pdf.py b/libmat2/pdf.py index 140b4f4..17cd61e 100644 --- a/libmat2/pdf.py +++ b/libmat2/pdf.py @@ -7,6 +7,7 @@ import re import logging import tempfile import io +from typing import Dict, Union from distutils.version import LooseVersion import cairo @@ -130,7 +131,7 @@ class PDFParser(abstract.AbstractParser): metadata[key] = value return metadata - def get_meta(self): + def get_meta(self) -> Dict[str, Union[str, dict]]: """ Return a dict with all the meta of the file """ metadata = {} diff --git a/libmat2/torrent.py b/libmat2/torrent.py index c56e971..4d6c1e0 100644 --- a/libmat2/torrent.py +++ b/libmat2/torrent.py @@ -14,7 +14,7 @@ class TorrentParser(abstract.AbstractParser): if self.dict_repr is None: raise ValueError - def get_meta(self) -> Dict[str, str]: + def get_meta(self) -> Dict[str, Union[str, dict]]: metadata = {} for key, value in self.dict_repr.items(): if key not in self.whitelist: -- cgit v1.3