Added tests and did improved class and file structure.
This commit is contained in:
parent
c6df2441f8
commit
dfa9ab6529
6 changed files with 87 additions and 39 deletions
|
@ -1,19 +1,18 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from __future__ import annotations
|
||||
from struct import pack
|
||||
from tinytag import TinyTag
|
||||
from io import BytesIO
|
||||
from tinytag import TinyTag, tinytag
|
||||
|
||||
from .. import SmallTag
|
||||
|
||||
if True:
|
||||
if False:
|
||||
from collections.abc import Callable, Iterator # noqa
|
||||
from typing import Any, BinaryIO, Dict, List
|
||||
|
||||
|
||||
_tinytag_id3 = TinyTag._get_parser_for_filename(".mp3") # noqa
|
||||
|
||||
|
||||
class _ID3(SmallTag, _tinytag_id3):
|
||||
class _ID3(SmallTag, tinytag._ID3):
|
||||
@staticmethod
|
||||
def _synchsafe(unsynchsafe_int: int) -> tuple[int, ...]:
|
||||
ints = (
|
||||
|
@ -41,7 +40,6 @@ class _ID3(SmallTag, _tinytag_id3):
|
|||
new_header = self._compose_id3v2_header(size)
|
||||
|
||||
new_tag = new_header + new_frames
|
||||
print(new_tag)
|
||||
|
||||
size, extended, major = self._parse_id3v2_header(self._filehandler)
|
||||
|
||||
|
|
|
@ -1,15 +1,29 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from __future__ import annotations
|
||||
from tinytag import TinyTag, UnsupportedFormatError
|
||||
from tinytag import tinytag
|
||||
|
||||
|
||||
if False: # just stole this lazy import type hinting trick from tinytag
|
||||
from collections.abc import Callable, Iterator # noqa
|
||||
from typing import Any, BinaryIO, Dict, List
|
||||
|
||||
TinyTag = tinytag.TinyTag
|
||||
UnsupportedFormatError = tinytag.UnsupportedFormatError
|
||||
|
||||
|
||||
class SmallTag(TinyTag):
|
||||
_file_extension_mapping: dict[tuple[str, ...], type[SmallTag]]= {
|
||||
(".mp1", ".mp2", ".mp3"): None,
|
||||
('.oga', '.ogg', '.opus', '.spx'): tinytag._Ogg,
|
||||
('.wav',): tinytag._Wave,
|
||||
('.flac',): tinytag._Flac,
|
||||
('.wma',): tinytag._Wma,
|
||||
('.m4b', '.m4a', '.m4r', '.m4v', '.mp4',
|
||||
'.aax', '.aaxc'): tinytag._MP4,
|
||||
('.aiff', '.aifc', '.aif', '.afc'): tinytag._Aiff,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def _get_parser_class(
|
||||
cls,
|
||||
|
@ -30,6 +44,37 @@ class SmallTag(TinyTag):
|
|||
raise UnsupportedFormatError(
|
||||
'No tag reader found to support file type')
|
||||
|
||||
@classmethod
|
||||
def _get_parser_for_file_handle(
|
||||
cls,
|
||||
filehandle: BinaryIO
|
||||
) -> type[SmallTag] | None:
|
||||
# https://en.wikipedia.org/wiki/List_of_file_signatures
|
||||
header = filehandle.read(35)
|
||||
filehandle.seek(0)
|
||||
if header.startswith(b'ID3') or header.startswith(b'\xff\xfb'):
|
||||
return _ID3
|
||||
|
||||
super()._get_parser_for_file_handle(filehandle)
|
||||
# if header.startswith(b'fLaC'):
|
||||
# return _Flac
|
||||
# if ((header[4:8] == b'ftyp'
|
||||
# and header[8:11] in {b'M4A', b'M4B', b'aax'})
|
||||
# or b'\xff\xf1' in header):
|
||||
# return _MP4
|
||||
# if (header.startswith(b'OggS')
|
||||
# and (header[29:33] == b'FLAC' or header[29:35] == b'vorbis'
|
||||
# or header[28:32] == b'Opus' or header[29:34] == b'Speex')):
|
||||
# return _Ogg
|
||||
# if header.startswith(b'RIFF') and header[8:12] == b'WAVE':
|
||||
# return _Wave
|
||||
# if header.startswith(b'\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00'
|
||||
# b'\xAA\x00\x62\xCE\x6C'):
|
||||
# return _Wma
|
||||
# if header.startswith(b'FORM') and header[8:12] in {b'AIFF', b'AIFC'}:
|
||||
# return _Aiff
|
||||
# return None
|
||||
|
||||
def write(self, file_obj: BinaryIO = None):
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -42,14 +87,14 @@ class SmallTag(TinyTag):
|
|||
"(Has to be from the same file as specified while creating this TinyTag instance.)"
|
||||
)
|
||||
|
||||
if file_obj is not None and not self._filehandler.closed():
|
||||
if file_obj is not None and not self._filehandler.closed:
|
||||
self._filehandler.close()
|
||||
|
||||
if file_obj is not None:
|
||||
self._filehandler = file_obj
|
||||
if file_obj is None:
|
||||
self._filehandler = open(self.filename, "rb+")
|
||||
|
||||
else:
|
||||
self._filehandler = open(self.filename, "rb+")
|
||||
self._filehandler = file_obj
|
||||
|
||||
return should_close_file
|
||||
|
||||
|
@ -58,13 +103,5 @@ class SmallTag(TinyTag):
|
|||
# (this solution is stupid, but I don't know anything better.)
|
||||
from ._formats import _ID3 # noqa
|
||||
|
||||
SmallTag._file_extension_mapping = {
|
||||
('.mp1', '.mp2', '.mp3'): _ID3,
|
||||
# ('.oga', '.ogg', '.opus', '.spx'): _Ogg, (Not yet implemented.)
|
||||
# ('.wav',): _Wave,
|
||||
# ('.flac',): _Flac,
|
||||
# ('.wma',): _Wma,
|
||||
# ('.m4b', '.m4a', '.m4r', '.m4v', '.mp4',
|
||||
# '.aax', '.aaxc'): _MP4,
|
||||
# ('.aiff', '.aifc', '.aif', '.afc'): _Aiff,
|
||||
}
|
||||
SmallTag._file_extension_mapping[(".mp1", ".mp2", ".mp3")] = _ID3
|
||||
|
||||
|
|
BIN
tests/formats/test.mp3
Normal file
BIN
tests/formats/test.mp3
Normal file
Binary file not shown.
30
tests/formats/test_id3.py
Normal file
30
tests/formats/test_id3.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from smalltag import SmallTag
|
||||
|
||||
|
||||
# chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ "
|
||||
|
||||
# no "b" because there is a bug in TinyTag 2.1.0 that removes "b"s if they are at the beginning of a string
|
||||
chars = "acdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789- _"
|
||||
|
||||
|
||||
def test_writing_text_frames():
|
||||
for char1 in chars:
|
||||
for char2 in chars:
|
||||
field_content = f"{char1}{char2}Test{char2}{char1}"
|
||||
|
||||
tag = SmallTag.get("formats/test.mp3")
|
||||
|
||||
tag.title = field_content
|
||||
tag.artist = field_content
|
||||
tag.album = field_content
|
||||
|
||||
tag.write()
|
||||
|
||||
tag = SmallTag.get("formats/test.mp3")
|
||||
|
||||
assert tag.title == field_content
|
||||
assert tag.artist == field_content
|
||||
assert tag.album == field_content
|
||||
|
17
tests/id3.py
17
tests/id3.py
|
@ -1,17 +0,0 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
from json import dumps
|
||||
from smalltag import SmallTag
|
||||
|
||||
|
||||
test_tag = SmallTag.get("test.mp3")
|
||||
print(test_tag)
|
||||
|
||||
print(test_tag.title)
|
||||
test_tag.title = "bTest"
|
||||
|
||||
test_tag.write()
|
||||
|
||||
test_tag = SmallTag.get("test.mp3")
|
||||
|
||||
print(dumps(test_tag.as_dict(), indent=" "))
|
BIN
tests/test.mp3
BIN
tests/test.mp3
Binary file not shown.
Loading…
Add table
Reference in a new issue