diff --git a/stagger/frames.py b/stagger/frames.py index f2b914e..ecf4984 100644 --- a/stagger/frames.py +++ b/stagger/frames.py @@ -34,12 +34,19 @@ import abc import collections -import imghdr from abc import abstractmethod from warnings import warn from stagger.errors import * from stagger.specs import * +from stagger.util import imghdr_what + +try: + from collections import Container + from collections import Iterable +except ImportError: + from collections.abc import Container + from collections.abc import Iterable class Frame(metaclass=abc.ABCMeta): _framespec = tuple() @@ -114,7 +121,7 @@ def _in_version(self, *versions): "Returns true if this frame is in any of the specified versions of ID3." for version in versions: if (self._version == version - or (isinstance(self._version, collections.Container) + or (isinstance(self._version, Container) and version in self._version)): return True return False @@ -244,7 +251,7 @@ def extract_strs(values): return if isinstance(values, str): yield values - elif isinstance(values, collections.Iterable): + elif isinstance(values, Iterable): for val in values: for v in extract_strs(val): yield v @@ -313,7 +320,7 @@ def __init__(self, value=None, frameid=None, flags=None, frameno=None, **kwargs) self.data = file.read() self.type = 0 self.desc = "" - format = imghdr.what(None, self.data[:32]) + format = imghdr_what(None, self.data[:32]) if not format: format = value.rpartition(".")[2] self._set_format(format) diff --git a/stagger/id3.py b/stagger/id3.py index 3fec68a..6105912 100644 --- a/stagger/id3.py +++ b/stagger/id3.py @@ -33,12 +33,11 @@ """List of frames defined in the various ID3 versions. """ -import imghdr - import stagger.tags as tags from stagger.frames import * from stagger.specs import * from stagger.tags import frameclass +from stagger.util import imghdr_what # ID3v2.4 @@ -422,7 +421,7 @@ def _to_version(self, version): def _str_fields(self): img = "{0} bytes of {1} data".format(len(self.data), - imghdr.what(None, self.data[:32])) + imghdr_what(None, self.data[:32])) return ("type={0}, desc={1}, mime={2}: {3}" .format(repr(self._spec("type").to_str(self.type)), repr(self.desc), @@ -819,7 +818,7 @@ def _to_version(self, version): elif self.format.upper() == "JPG": mime = "image/jpeg" else: - mime = imghdr.what(io.StringIO(self.data)) + mime = imghdr_what(io.StringIO(self.data)) if mime is None: raise ValueError("Unknown image format") mime = "image/" + mime.lower() @@ -827,7 +826,7 @@ def _to_version(self, version): def _str_fields(self): img = "{0} bytes of {1} data".format(len(self.data), - imghdr.what(None, self.data[:32])) + imghdr_what(None, self.data[:32])) return ("type={0}, desc={1}, format={2}: {3}" .format(repr(self._spec("type").to_str(self.type)), repr(self.desc), diff --git a/stagger/specs.py b/stagger/specs.py index 1567a5f..a39b9c9 100644 --- a/stagger/specs.py +++ b/stagger/specs.py @@ -39,6 +39,13 @@ from stagger.conversion import * from stagger.errors import * +try: + from collections import ByteString + from collections import Sequence +except ImportError: + from collections.abc import ByteString + from collections.abc import Sequence + # The idea for the Spec system comes from Mutagen. def optionalspec(spec): @@ -228,7 +235,7 @@ def write(self, frame, value): def validate(self, frame, value): if value is None: return bytes() - if not isinstance(value, collections.ByteString): + if not isinstance(value, ByteString): raise TypeError("Not a byte sequence") return value def to_str(self, value): @@ -423,7 +430,7 @@ def validate(self, frame, values): return [] res = [] for v in values: - if not isinstance(v, collections.Sequence) or isinstance(v, str): + if not isinstance(v, Sequence) or isinstance(v, str): raise TypeError("Records must be sequences") if len(v) != len(self.specs): raise ValueError("Invalid record length") @@ -453,7 +460,7 @@ def write(self, frame, values): def validate(self, frame, values): if values is None: return [] - if not isinstance(values, collections.Sequence) or isinstance(values, str): + if not isinstance(values, Sequence) or isinstance(values, str): raise TypeError("ASPISpec needs a sequence of integers") if len(values) != frame.N: raise ValueError("ASPISpec needs {0} integers".format(frame.N)) diff --git a/stagger/tags.py b/stagger/tags.py index 3949d99..a002452 100644 --- a/stagger/tags.py +++ b/stagger/tags.py @@ -35,7 +35,6 @@ import re import collections import io -import imghdr import zlib from abc import abstractmethod, abstractproperty @@ -47,6 +46,14 @@ import stagger.frames as Frames import stagger.fileutil as fileutil +from stagger.util import imghdr_what + +try: + from collections import MutableMapping + from collections import Iterable +except ImportError: + from collections.abc import MutableMapping + from collections.abc import Iterable _FRAME23_FORMAT_COMPRESSED = 0x0080 _FRAME23_FORMAT_ENCRYPTED = 0x0040 @@ -219,7 +226,7 @@ def __repr__(self): return "".format(", ".join(pair[0] for pair in order)) -class Tag(collections.MutableMapping, metaclass=abc.ABCMeta): +class Tag(MutableMapping, metaclass=abc.ABCMeta): known_frames = { } # Maps known frameids to Frame class objects frame_order = None # Initialized by stagger.id3 @@ -316,7 +323,7 @@ def __setitem__(self, key, value): self._frames[key] = [value] return if self.known_frames[key]._allow_duplicates: - if not isinstance(value, collections.Iterable) or isinstance(value, str): + if not isinstance(value, Iterable) or isinstance(value, str): raise ValueError("{0} requires a list of frame values".format(key)) self._frames[key] = [val if isinstance(val, self.known_frames[key]) else self.known_frames[key](val) @@ -484,8 +491,8 @@ def _get_date(self, yearframe, dateframe, timeframe): try: time = self.__friendly_text_collect(timeframe)[0] m = re.match(r"\s*(?P[0-2][0-9])\s*:?\s*" - "(?P[0-5][0-9])\s*:?\s*" - "(?P[0-5][0-9])?\s*$", time) + r"(?P[0-5][0-9])\s*:?\s*" + r"(?P[0-5][0-9])?\s*$", time) if m is not None: hour = int(m.group("hour")) minute = int(m.group("minute")) @@ -516,7 +523,7 @@ def getter(self): .format(f._spec("type").to_str(f.type), f.desc, len(f.data), - imghdr.what(None, f.data[:32])) + imghdr_what(None, f.data[:32])) for f in self[frameid]) def setter(self, value): if len(value) > 0: diff --git a/stagger/util.py b/stagger/util.py index 6b29cb0..52727bf 100644 --- a/stagger/util.py +++ b/stagger/util.py @@ -137,3 +137,8 @@ def print_warnings(filename, options): print(filename + ":warning: " + str(w.message), file=sys.stderr) sys.stderr.flush() + +def imghdr_what(file, h): + # imhdr.what was deprecated in PEP-0594 + # See https://peps.python.org/pep-0594/#imghdr + return None