Implemented writing of link frames.
This commit is contained in:
parent
d48394a522
commit
2db7097fdf
4 changed files with 50 additions and 13 deletions
|
@ -4,9 +4,9 @@ A module that extends TinyTag's capabilities by also writing tags.
|
|||
|
||||
### Features
|
||||
|
||||
| Feature | Sub-Features | State |
|
||||
|-------------|-------------------------------------------------------------------|--------------------------------------------------------|
|
||||
| ID3-Writing | <input type="checkbox" disabled checked> Writing Of String Frames | <input type="checkbox" disabled> Partially Implemented |
|
||||
| Feature | Sub-Features | State |
|
||||
|-------------|--------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|
|
||||
| ID3-Writing | <input type="checkbox" disabled checked> Writing Of String Frames<br><input type="checkbox" disabled checked> Writing Of Link Frames | <input type="checkbox" disabled> Partially Implemented |
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from __future__ import annotations
|
||||
from struct import pack
|
||||
from io import BytesIO
|
||||
from tinytag import TinyTag, tinytag
|
||||
|
||||
from .. import SmallTag
|
||||
|
@ -24,10 +23,10 @@ class _ID3(SmallTag, tinytag._ID3):
|
|||
|
||||
return ints
|
||||
|
||||
def write(self, file_obj: BinaryIO=None):
|
||||
def write(self, advanced: dict[str, str | float | list[str]] | None=None, file_obj: BinaryIO=None) -> None:
|
||||
should_close_file = self._set_filehandler_for_writing(file_obj)
|
||||
|
||||
new_tag = self._compose_id3v2_tag()
|
||||
new_tag = self._compose_id3v2_tag(advanced)
|
||||
|
||||
size, extended, major = self._parse_id3v2_header(self._filehandler)
|
||||
|
||||
|
@ -41,14 +40,17 @@ class _ID3(SmallTag, tinytag._ID3):
|
|||
if should_close_file:
|
||||
self._filehandler.close()
|
||||
|
||||
def _compose_id3v2_tag(self) -> bytes:
|
||||
def compose_tag(self, advanced: dict | None=None) -> bytes:
|
||||
return self._compose_id3v2_tag(advanced)
|
||||
|
||||
def _compose_id3v2_tag(self, advanced: dict | None=None) -> bytes:
|
||||
# change keys to values in the mapping dict
|
||||
self._ID3_WRITE_MAPPING = {} # noqa
|
||||
for frame_id, name in self._ID3_MAPPING.items():
|
||||
if len(frame_id) == 4:
|
||||
self._ID3_WRITE_MAPPING[name] = frame_id
|
||||
|
||||
frames = self._compose_id3v2_frames()
|
||||
frames = self._compose_id3v2_frames(advanced)
|
||||
frame_size = len(frames)
|
||||
|
||||
header = self._compose_id3v2_header(frame_size)
|
||||
|
@ -65,13 +67,22 @@ class _ID3(SmallTag, tinytag._ID3):
|
|||
|
||||
return header
|
||||
|
||||
def _compose_id3v2_frames(self) -> bytes:
|
||||
tag_dict = self.as_dict()
|
||||
def _compose_id3v2_frames(self, advanced: dict | None=None) -> bytes:
|
||||
if advanced is None:
|
||||
tag_dict = self.as_dict()
|
||||
|
||||
else:
|
||||
tag_dict = advanced
|
||||
|
||||
frames = b""
|
||||
|
||||
for field_name, field_value in tag_dict.items():
|
||||
if field_name not in self._ID3_WRITE_MAPPING:
|
||||
other_field = "other." + field_name
|
||||
|
||||
if other_field in self._ID3_WRITE_MAPPING:
|
||||
frames += self._compose_id3v2_frame(other_field, field_value)
|
||||
|
||||
continue
|
||||
|
||||
frames += self._compose_id3v2_frame(field_name, field_value)
|
||||
|
@ -85,7 +96,12 @@ class _ID3(SmallTag, tinytag._ID3):
|
|||
field_value = field_value[0]
|
||||
|
||||
if isinstance(field_value, str):
|
||||
frame_value = b"\x00" + bytes(field_value, "ISO-8859-1")
|
||||
frame_value = bytes(field_value, "ISO-8859-1")
|
||||
|
||||
# set format byte to ISO-8859-1 on normal text frames
|
||||
# (link-frames are always ISO-8859-1 formatted and don't need the format byte)
|
||||
if frame_id.startswith(b"T"):
|
||||
frame_value = b"\x00" + frame_value
|
||||
|
||||
elif isinstance(field_value, int) and frame_id.startswith(b"T"):
|
||||
frame_value = b"\x00" + bytes(str(field_value), "ISO-8859-1")
|
||||
|
|
|
@ -75,7 +75,22 @@ class SmallTag(TinyTag):
|
|||
# return _Aiff
|
||||
# return None
|
||||
|
||||
def write(self, file_obj: BinaryIO = None):
|
||||
def write(self, advanced: dict[str, str | float | list[str]] | None=None, file_obj: BinaryIO = None):
|
||||
"""
|
||||
Write to the file given at creation of the tag or to the file object given to this function.
|
||||
:param advanced: Dict containing fields to write.
|
||||
:param file_obj: File object to write to. (Has to be in "rb+" mode.)
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
def compose_tag(self, advanced: dict[str, str | float | list[str]] | None=None) -> bytes:
|
||||
"""
|
||||
Only compose a tag without writing.
|
||||
:param advanced: Dict containing fields to write.
|
||||
:return: Composed tag as bytes.
|
||||
"""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
def _set_filehandler_for_writing(self, file_obj: BinaryIO) -> bool:
|
||||
|
|
|
@ -14,13 +14,15 @@ def test_written_gets_recognized():
|
|||
tag.artist = "An artist."
|
||||
tag.album = "The album."
|
||||
tag.track = 1234
|
||||
tag.other["url"] = ["https://teapot.informationsanarchistik.de/Wobbl/SmallTag"]
|
||||
|
||||
tag = SmallTag.get("formats/test.mp3", file_obj=BytesIO(tag._compose_id3v2_tag()))
|
||||
tag = SmallTag.get("formats/test.mp3", file_obj=BytesIO(tag.compose_tag()))
|
||||
|
||||
assert tag.title == "A normal title."
|
||||
assert tag.artist == "An artist."
|
||||
assert tag.album == "The album."
|
||||
assert tag.track == 1234
|
||||
assert tag.other["url"] == ["https://teapot.informationsanarchistik.de/Wobbl/SmallTag"]
|
||||
|
||||
|
||||
# chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_ "
|
||||
|
@ -39,6 +41,8 @@ def test_full_written_gets_recognized():
|
|||
tag.title = field_content
|
||||
tag.artist = field_content
|
||||
tag.album = field_content
|
||||
tag.track = 1234
|
||||
tag.other["url"] = ["https://teapot.informationsanarchistik.de/Wobbl/SmallTag"]
|
||||
|
||||
tag.write()
|
||||
|
||||
|
@ -47,3 +51,5 @@ def test_full_written_gets_recognized():
|
|||
assert tag.title == field_content
|
||||
assert tag.artist == field_content
|
||||
assert tag.album == field_content
|
||||
assert tag.track == 1234
|
||||
assert tag.other["url"] == ["https://teapot.informationsanarchistik.de/Wobbl/SmallTag"]
|
||||
|
|
Loading…
Add table
Reference in a new issue